MLIR  22.0.0git
LLVMDialect.cpp
Go to the documentation of this file.
1 //===- LLVMDialect.cpp - LLVM IR Ops and Dialect registration -------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the types and operation details for the LLVM IR dialect in
10 // MLIR, and the LLVM IR dialect. It also registers the dialect.
11 //
12 //===----------------------------------------------------------------------===//
13 
17 #include "mlir/IR/Attributes.h"
18 #include "mlir/IR/Builders.h"
19 #include "mlir/IR/BuiltinOps.h"
20 #include "mlir/IR/BuiltinTypes.h"
22 #include "mlir/IR/MLIRContext.h"
23 #include "mlir/IR/Matchers.h"
26 
27 #include "llvm/ADT/APFloat.h"
28 #include "llvm/ADT/TypeSwitch.h"
29 #include "llvm/IR/DataLayout.h"
30 #include "llvm/Support/Error.h"
31 
32 #include <numeric>
33 #include <optional>
34 
35 using namespace mlir;
36 using namespace mlir::LLVM;
37 using mlir::LLVM::cconv::getMaxEnumValForCConv;
38 using mlir::LLVM::linkage::getMaxEnumValForLinkage;
39 using mlir::LLVM::tailcallkind::getMaxEnumValForTailCallKind;
40 
41 #include "mlir/Dialect/LLVMIR/LLVMOpsDialect.cpp.inc"
42 
43 //===----------------------------------------------------------------------===//
44 // Attribute Helpers
45 //===----------------------------------------------------------------------===//
46 
47 static constexpr const char kElemTypeAttrName[] = "elem_type";
48 
50  SmallVector<NamedAttribute, 8> filteredAttrs(
51  llvm::make_filter_range(attrs, [&](NamedAttribute attr) {
52  if (attr.getName() == "fastmathFlags") {
53  auto defAttr =
54  FastmathFlagsAttr::get(attr.getValue().getContext(), {});
55  return defAttr != attr.getValue();
56  }
57  return true;
58  }));
59  return filteredAttrs;
60 }
61 
62 /// Verifies `symbol`'s use in `op` to ensure the symbol is a valid and
63 /// fully defined llvm.func.
64 static LogicalResult verifySymbolAttrUse(FlatSymbolRefAttr symbol,
65  Operation *op,
66  SymbolTableCollection &symbolTable) {
67  StringRef name = symbol.getValue();
68  auto func =
69  symbolTable.lookupNearestSymbolFrom<LLVMFuncOp>(op, symbol.getAttr());
70  if (!func)
71  return op->emitOpError("'")
72  << name << "' does not reference a valid LLVM function";
73  if (func.isExternal())
74  return op->emitOpError("'") << name << "' does not have a definition";
75  return success();
76 }
77 
78 /// Returns a boolean type that has the same shape as `type`. It supports both
79 /// fixed size vectors as well as scalable vectors.
80 static Type getI1SameShape(Type type) {
81  Type i1Type = IntegerType::get(type.getContext(), 1);
83  return LLVM::getVectorType(i1Type, LLVM::getVectorNumElements(type));
84  return i1Type;
85 }
86 
87 // Parses one of the keywords provided in the list `keywords` and returns the
88 // position of the parsed keyword in the list. If none of the keywords from the
89 // list is parsed, returns -1.
91  ArrayRef<StringRef> keywords) {
92  for (const auto &en : llvm::enumerate(keywords)) {
93  if (succeeded(parser.parseOptionalKeyword(en.value())))
94  return en.index();
95  }
96  return -1;
97 }
98 
99 namespace {
100 template <typename Ty>
101 struct EnumTraits {};
102 
103 #define REGISTER_ENUM_TYPE(Ty) \
104  template <> \
105  struct EnumTraits<Ty> { \
106  static StringRef stringify(Ty value) { return stringify##Ty(value); } \
107  static unsigned getMaxEnumVal() { return getMaxEnumValFor##Ty(); } \
108  }
109 
110 REGISTER_ENUM_TYPE(Linkage);
111 REGISTER_ENUM_TYPE(UnnamedAddr);
112 REGISTER_ENUM_TYPE(CConv);
113 REGISTER_ENUM_TYPE(TailCallKind);
115 } // namespace
116 
117 /// Parse an enum from the keyword, or default to the provided default value.
118 /// The return type is the enum type by default, unless overridden with the
119 /// second template argument.
120 template <typename EnumTy, typename RetTy = EnumTy>
122  EnumTy defaultValue) {
124  for (unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
125  names.push_back(EnumTraits<EnumTy>::stringify(static_cast<EnumTy>(i)));
126 
127  int index = parseOptionalKeywordAlternative(parser, names);
128  if (index == -1)
129  return static_cast<RetTy>(defaultValue);
130  return static_cast<RetTy>(index);
131 }
132 
133 static void printLLVMLinkage(OpAsmPrinter &p, Operation *, LinkageAttr val) {
134  p << stringifyLinkage(val.getLinkage());
135 }
136 
137 static ParseResult parseLLVMLinkage(OpAsmParser &p, LinkageAttr &val) {
138  val = LinkageAttr::get(
139  p.getContext(),
140  parseOptionalLLVMKeyword<LLVM::Linkage>(p, LLVM::Linkage::External));
141  return success();
142 }
143 
145  bool isExpandLoad,
146  uint64_t alignment = 1) {
147  // From
148  // https://llvm.org/docs/LangRef.html#llvm-masked-expandload-intrinsics
149  // https://llvm.org/docs/LangRef.html#llvm-masked-compressstore-intrinsics
150  //
151  // The pointer alignment defaults to 1.
152  if (alignment == 1) {
153  return nullptr;
154  }
155 
156  auto emptyDictAttr = builder.getDictionaryAttr({});
157  auto alignmentAttr = builder.getI64IntegerAttr(alignment);
158  auto namedAttr =
159  builder.getNamedAttr(LLVMDialect::getAlignAttrName(), alignmentAttr);
160  SmallVector<mlir::NamedAttribute> attrs = {namedAttr};
161  auto alignDictAttr = builder.getDictionaryAttr(attrs);
162  // From
163  // https://llvm.org/docs/LangRef.html#llvm-masked-expandload-intrinsics
164  // https://llvm.org/docs/LangRef.html#llvm-masked-compressstore-intrinsics
165  //
166  // The align parameter attribute can be provided for [expandload]'s first
167  // argument. The align parameter attribute can be provided for
168  // [compressstore]'s second argument.
169  int pos = isExpandLoad ? 0 : 1;
170  return pos == 0 ? builder.getArrayAttr(
171  {alignDictAttr, emptyDictAttr, emptyDictAttr})
172  : builder.getArrayAttr(
173  {emptyDictAttr, alignDictAttr, emptyDictAttr});
174 }
175 
176 //===----------------------------------------------------------------------===//
177 // Operand bundle helpers.
178 //===----------------------------------------------------------------------===//
179 
180 static void printOneOpBundle(OpAsmPrinter &p, OperandRange operands,
181  TypeRange operandTypes, StringRef tag) {
182  p.printString(tag);
183  p << "(";
184 
185  if (!operands.empty()) {
186  p.printOperands(operands);
187  p << " : ";
188  llvm::interleaveComma(operandTypes, p);
189  }
190 
191  p << ")";
192 }
193 
195  OperandRangeRange opBundleOperands,
196  TypeRangeRange opBundleOperandTypes,
197  std::optional<ArrayAttr> opBundleTags) {
198  if (opBundleOperands.empty())
199  return;
200  assert(opBundleTags && "expect operand bundle tags");
201 
202  p << "[";
203  llvm::interleaveComma(
204  llvm::zip(opBundleOperands, opBundleOperandTypes, *opBundleTags), p,
205  [&p](auto bundle) {
206  auto bundleTag = cast<StringAttr>(std::get<2>(bundle)).getValue();
207  printOneOpBundle(p, std::get<0>(bundle), std::get<1>(bundle),
208  bundleTag);
209  });
210  p << "]";
211 }
212 
213 static ParseResult parseOneOpBundle(
214  OpAsmParser &p,
216  SmallVector<SmallVector<Type>> &opBundleOperandTypes,
217  SmallVector<Attribute> &opBundleTags) {
218  SMLoc currentParserLoc = p.getCurrentLocation();
220  SmallVector<Type> types;
221  std::string tag;
222 
223  if (p.parseString(&tag))
224  return p.emitError(currentParserLoc, "expect operand bundle tag");
225 
226  if (p.parseLParen())
227  return failure();
228 
229  if (p.parseOptionalRParen()) {
230  if (p.parseOperandList(operands) || p.parseColon() ||
231  p.parseTypeList(types) || p.parseRParen())
232  return failure();
233  }
234 
235  opBundleOperands.push_back(std::move(operands));
236  opBundleOperandTypes.push_back(std::move(types));
237  opBundleTags.push_back(StringAttr::get(p.getContext(), tag));
238 
239  return success();
240 }
241 
242 static std::optional<ParseResult> parseOpBundles(
243  OpAsmParser &p,
245  SmallVector<SmallVector<Type>> &opBundleOperandTypes,
246  ArrayAttr &opBundleTags) {
247  if (p.parseOptionalLSquare())
248  return std::nullopt;
249 
250  if (succeeded(p.parseOptionalRSquare()))
251  return success();
252 
253  SmallVector<Attribute> opBundleTagAttrs;
254  auto bundleParser = [&] {
255  return parseOneOpBundle(p, opBundleOperands, opBundleOperandTypes,
256  opBundleTagAttrs);
257  };
258  if (p.parseCommaSeparatedList(bundleParser))
259  return failure();
260 
261  if (p.parseRSquare())
262  return failure();
263 
264  opBundleTags = ArrayAttr::get(p.getContext(), opBundleTagAttrs);
265 
266  return success();
267 }
268 
269 //===----------------------------------------------------------------------===//
270 // Printing, parsing, folding and builder for LLVM::CmpOp.
271 //===----------------------------------------------------------------------===//
272 
273 void ICmpOp::print(OpAsmPrinter &p) {
274  p << " \"" << stringifyICmpPredicate(getPredicate()) << "\" " << getOperand(0)
275  << ", " << getOperand(1);
276  p.printOptionalAttrDict((*this)->getAttrs(), {"predicate"});
277  p << " : " << getLhs().getType();
278 }
279 
280 void FCmpOp::print(OpAsmPrinter &p) {
281  p << " \"" << stringifyFCmpPredicate(getPredicate()) << "\" " << getOperand(0)
282  << ", " << getOperand(1);
283  p.printOptionalAttrDict(processFMFAttr((*this)->getAttrs()), {"predicate"});
284  p << " : " << getLhs().getType();
285 }
286 
287 // <operation> ::= `llvm.icmp` string-literal ssa-use `,` ssa-use
288 // attribute-dict? `:` type
289 // <operation> ::= `llvm.fcmp` string-literal ssa-use `,` ssa-use
290 // attribute-dict? `:` type
291 template <typename CmpPredicateType>
292 static ParseResult parseCmpOp(OpAsmParser &parser, OperationState &result) {
293  StringAttr predicateAttr;
295  Type type;
296  SMLoc predicateLoc, trailingTypeLoc;
297  if (parser.getCurrentLocation(&predicateLoc) ||
298  parser.parseAttribute(predicateAttr, "predicate", result.attributes) ||
299  parser.parseOperand(lhs) || parser.parseComma() ||
300  parser.parseOperand(rhs) ||
301  parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
302  parser.getCurrentLocation(&trailingTypeLoc) || parser.parseType(type) ||
303  parser.resolveOperand(lhs, type, result.operands) ||
304  parser.resolveOperand(rhs, type, result.operands))
305  return failure();
306 
307  // Replace the string attribute `predicate` with an integer attribute.
308  int64_t predicateValue = 0;
309  if (std::is_same<CmpPredicateType, ICmpPredicate>()) {
310  std::optional<ICmpPredicate> predicate =
311  symbolizeICmpPredicate(predicateAttr.getValue());
312  if (!predicate)
313  return parser.emitError(predicateLoc)
314  << "'" << predicateAttr.getValue()
315  << "' is an incorrect value of the 'predicate' attribute";
316  predicateValue = static_cast<int64_t>(*predicate);
317  } else {
318  std::optional<FCmpPredicate> predicate =
319  symbolizeFCmpPredicate(predicateAttr.getValue());
320  if (!predicate)
321  return parser.emitError(predicateLoc)
322  << "'" << predicateAttr.getValue()
323  << "' is an incorrect value of the 'predicate' attribute";
324  predicateValue = static_cast<int64_t>(*predicate);
325  }
326 
327  result.attributes.set("predicate",
328  parser.getBuilder().getI64IntegerAttr(predicateValue));
329 
330  // The result type is either i1 or a vector type <? x i1> if the inputs are
331  // vectors.
332  if (!isCompatibleType(type))
333  return parser.emitError(trailingTypeLoc,
334  "expected LLVM dialect-compatible type");
335  result.addTypes(getI1SameShape(type));
336  return success();
337 }
338 
339 ParseResult ICmpOp::parse(OpAsmParser &parser, OperationState &result) {
340  return parseCmpOp<ICmpPredicate>(parser, result);
341 }
342 
343 ParseResult FCmpOp::parse(OpAsmParser &parser, OperationState &result) {
344  return parseCmpOp<FCmpPredicate>(parser, result);
345 }
346 
347 /// Returns a scalar or vector boolean attribute of the given type.
348 static Attribute getBoolAttribute(Type type, MLIRContext *ctx, bool value) {
349  auto boolAttr = BoolAttr::get(ctx, value);
350  ShapedType shapedType = dyn_cast<ShapedType>(type);
351  if (!shapedType)
352  return boolAttr;
353  return DenseElementsAttr::get(shapedType, boolAttr);
354 }
355 
356 OpFoldResult ICmpOp::fold(FoldAdaptor adaptor) {
357  if (getPredicate() != ICmpPredicate::eq &&
358  getPredicate() != ICmpPredicate::ne)
359  return {};
360 
361  // cmpi(eq/ne, x, x) -> true/false
362  if (getLhs() == getRhs())
363  return getBoolAttribute(getType(), getContext(),
364  getPredicate() == ICmpPredicate::eq);
365 
366  // cmpi(eq/ne, alloca, null) -> false/true
367  if (getLhs().getDefiningOp<AllocaOp>() && getRhs().getDefiningOp<ZeroOp>())
368  return getBoolAttribute(getType(), getContext(),
369  getPredicate() == ICmpPredicate::ne);
370 
371  // cmpi(eq/ne, null, alloca) -> cmpi(eq/ne, alloca, null)
372  if (getLhs().getDefiningOp<ZeroOp>() && getRhs().getDefiningOp<AllocaOp>()) {
373  Value lhs = getLhs();
374  Value rhs = getRhs();
375  getLhsMutable().assign(rhs);
376  getRhsMutable().assign(lhs);
377  return getResult();
378  }
379 
380  return {};
381 }
382 
383 //===----------------------------------------------------------------------===//
384 // Printing, parsing and verification for LLVM::AllocaOp.
385 //===----------------------------------------------------------------------===//
386 
387 void AllocaOp::print(OpAsmPrinter &p) {
388  auto funcTy =
389  FunctionType::get(getContext(), {getArraySize().getType()}, {getType()});
390 
391  if (getInalloca())
392  p << " inalloca";
393 
394  p << ' ' << getArraySize() << " x " << getElemType();
395  if (getAlignment() && *getAlignment() != 0)
396  p.printOptionalAttrDict((*this)->getAttrs(),
397  {kElemTypeAttrName, getInallocaAttrName()});
398  else
400  (*this)->getAttrs(),
401  {getAlignmentAttrName(), kElemTypeAttrName, getInallocaAttrName()});
402  p << " : " << funcTy;
403 }
404 
405 // <operation> ::= `llvm.alloca` `inalloca`? ssa-use `x` type
406 // attribute-dict? `:` type `,` type
407 ParseResult AllocaOp::parse(OpAsmParser &parser, OperationState &result) {
409  Type type, elemType;
410  SMLoc trailingTypeLoc;
411 
412  if (succeeded(parser.parseOptionalKeyword("inalloca")))
413  result.addAttribute(getInallocaAttrName(result.name),
414  UnitAttr::get(parser.getContext()));
415 
416  if (parser.parseOperand(arraySize) || parser.parseKeyword("x") ||
417  parser.parseType(elemType) ||
418  parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
419  parser.getCurrentLocation(&trailingTypeLoc) || parser.parseType(type))
420  return failure();
421 
422  std::optional<NamedAttribute> alignmentAttr =
423  result.attributes.getNamed("alignment");
424  if (alignmentAttr.has_value()) {
425  auto alignmentInt = llvm::dyn_cast<IntegerAttr>(alignmentAttr->getValue());
426  if (!alignmentInt)
427  return parser.emitError(parser.getNameLoc(),
428  "expected integer alignment");
429  if (alignmentInt.getValue().isZero())
430  result.attributes.erase("alignment");
431  }
432 
433  // Extract the result type from the trailing function type.
434  auto funcType = llvm::dyn_cast<FunctionType>(type);
435  if (!funcType || funcType.getNumInputs() != 1 ||
436  funcType.getNumResults() != 1)
437  return parser.emitError(
438  trailingTypeLoc,
439  "expected trailing function type with one argument and one result");
440 
441  if (parser.resolveOperand(arraySize, funcType.getInput(0), result.operands))
442  return failure();
443 
444  Type resultType = funcType.getResult(0);
445  if (auto ptrResultType = llvm::dyn_cast<LLVMPointerType>(resultType))
446  result.addAttribute(kElemTypeAttrName, TypeAttr::get(elemType));
447 
448  result.addTypes({funcType.getResult(0)});
449  return success();
450 }
451 
452 LogicalResult AllocaOp::verify() {
453  // Only certain target extension types can be used in 'alloca'.
454  if (auto targetExtType = dyn_cast<LLVMTargetExtType>(getElemType());
455  targetExtType && !targetExtType.supportsMemOps())
456  return emitOpError()
457  << "this target extension type cannot be used in alloca";
458 
459  return success();
460 }
461 
462 //===----------------------------------------------------------------------===//
463 // LLVM::BrOp
464 //===----------------------------------------------------------------------===//
465 
467  assert(index == 0 && "invalid successor index");
468  return SuccessorOperands(getDestOperandsMutable());
469 }
470 
471 //===----------------------------------------------------------------------===//
472 // LLVM::CondBrOp
473 //===----------------------------------------------------------------------===//
474 
476  assert(index < getNumSuccessors() && "invalid successor index");
477  return SuccessorOperands(index == 0 ? getTrueDestOperandsMutable()
478  : getFalseDestOperandsMutable());
479 }
480 
481 void CondBrOp::build(OpBuilder &builder, OperationState &result,
482  Value condition, Block *trueDest, ValueRange trueOperands,
483  Block *falseDest, ValueRange falseOperands,
484  std::optional<std::pair<uint32_t, uint32_t>> weights) {
485  DenseI32ArrayAttr weightsAttr;
486  if (weights)
487  weightsAttr =
488  builder.getDenseI32ArrayAttr({static_cast<int32_t>(weights->first),
489  static_cast<int32_t>(weights->second)});
490 
491  build(builder, result, condition, trueOperands, falseOperands, weightsAttr,
492  /*loop_annotation=*/{}, trueDest, falseDest);
493 }
494 
495 //===----------------------------------------------------------------------===//
496 // LLVM::SwitchOp
497 //===----------------------------------------------------------------------===//
498 
499 void SwitchOp::build(OpBuilder &builder, OperationState &result, Value value,
500  Block *defaultDestination, ValueRange defaultOperands,
501  DenseIntElementsAttr caseValues,
502  BlockRange caseDestinations,
503  ArrayRef<ValueRange> caseOperands,
504  ArrayRef<int32_t> branchWeights) {
505  DenseI32ArrayAttr weightsAttr;
506  if (!branchWeights.empty())
507  weightsAttr = builder.getDenseI32ArrayAttr(branchWeights);
508 
509  build(builder, result, value, defaultOperands, caseOperands, caseValues,
510  weightsAttr, defaultDestination, caseDestinations);
511 }
512 
513 void SwitchOp::build(OpBuilder &builder, OperationState &result, Value value,
514  Block *defaultDestination, ValueRange defaultOperands,
515  ArrayRef<APInt> caseValues, BlockRange caseDestinations,
516  ArrayRef<ValueRange> caseOperands,
517  ArrayRef<int32_t> branchWeights) {
518  DenseIntElementsAttr caseValuesAttr;
519  if (!caseValues.empty()) {
520  ShapedType caseValueType = VectorType::get(
521  static_cast<int64_t>(caseValues.size()), value.getType());
522  caseValuesAttr = DenseIntElementsAttr::get(caseValueType, caseValues);
523  }
524 
525  build(builder, result, value, defaultDestination, defaultOperands,
526  caseValuesAttr, caseDestinations, caseOperands, branchWeights);
527 }
528 
529 void SwitchOp::build(OpBuilder &builder, OperationState &result, Value value,
530  Block *defaultDestination, ValueRange defaultOperands,
531  ArrayRef<int32_t> caseValues, BlockRange caseDestinations,
532  ArrayRef<ValueRange> caseOperands,
533  ArrayRef<int32_t> branchWeights) {
534  DenseIntElementsAttr caseValuesAttr;
535  if (!caseValues.empty()) {
536  ShapedType caseValueType = VectorType::get(
537  static_cast<int64_t>(caseValues.size()), value.getType());
538  caseValuesAttr = DenseIntElementsAttr::get(caseValueType, caseValues);
539  }
540 
541  build(builder, result, value, defaultDestination, defaultOperands,
542  caseValuesAttr, caseDestinations, caseOperands, branchWeights);
543 }
544 
545 /// <cases> ::= `[` (case (`,` case )* )? `]`
546 /// <case> ::= integer `:` bb-id (`(` ssa-use-and-type-list `)`)?
547 static ParseResult parseSwitchOpCases(
548  OpAsmParser &parser, Type flagType, DenseIntElementsAttr &caseValues,
549  SmallVectorImpl<Block *> &caseDestinations,
551  SmallVectorImpl<SmallVector<Type>> &caseOperandTypes) {
552  if (failed(parser.parseLSquare()))
553  return failure();
554  if (succeeded(parser.parseOptionalRSquare()))
555  return success();
556  SmallVector<APInt> values;
557  unsigned bitWidth = flagType.getIntOrFloatBitWidth();
558  auto parseCase = [&]() {
559  int64_t value = 0;
560  if (failed(parser.parseInteger(value)))
561  return failure();
562  values.push_back(APInt(bitWidth, value, /*isSigned=*/true));
563 
564  Block *destination;
566  SmallVector<Type> operandTypes;
567  if (parser.parseColon() || parser.parseSuccessor(destination))
568  return failure();
569  if (!parser.parseOptionalLParen()) {
570  if (parser.parseOperandList(operands, OpAsmParser::Delimiter::None,
571  /*allowResultNumber=*/false) ||
572  parser.parseColonTypeList(operandTypes) || parser.parseRParen())
573  return failure();
574  }
575  caseDestinations.push_back(destination);
576  caseOperands.emplace_back(operands);
577  caseOperandTypes.emplace_back(operandTypes);
578  return success();
579  };
580  if (failed(parser.parseCommaSeparatedList(parseCase)))
581  return failure();
582 
583  ShapedType caseValueType =
584  VectorType::get(static_cast<int64_t>(values.size()), flagType);
585  caseValues = DenseIntElementsAttr::get(caseValueType, values);
586  return parser.parseRSquare();
587 }
588 
589 static void printSwitchOpCases(OpAsmPrinter &p, SwitchOp op, Type flagType,
590  DenseIntElementsAttr caseValues,
591  SuccessorRange caseDestinations,
592  OperandRangeRange caseOperands,
593  const TypeRangeRange &caseOperandTypes) {
594  p << '[';
595  p.printNewline();
596  if (!caseValues) {
597  p << ']';
598  return;
599  }
600 
601  size_t index = 0;
602  llvm::interleave(
603  llvm::zip(caseValues, caseDestinations),
604  [&](auto i) {
605  p << " ";
606  p << std::get<0>(i);
607  p << ": ";
608  p.printSuccessorAndUseList(std::get<1>(i), caseOperands[index++]);
609  },
610  [&] {
611  p << ',';
612  p.printNewline();
613  });
614  p.printNewline();
615  p << ']';
616 }
617 
618 LogicalResult SwitchOp::verify() {
619  if ((!getCaseValues() && !getCaseDestinations().empty()) ||
620  (getCaseValues() &&
621  getCaseValues()->size() !=
622  static_cast<int64_t>(getCaseDestinations().size())))
623  return emitOpError("expects number of case values to match number of "
624  "case destinations");
625  if (getCaseValues() &&
626  getValue().getType() != getCaseValues()->getElementType())
627  return emitError("expects case value type to match condition value type");
628  return success();
629 }
630 
632  assert(index < getNumSuccessors() && "invalid successor index");
633  return SuccessorOperands(index == 0 ? getDefaultOperandsMutable()
634  : getCaseOperandsMutable(index - 1));
635 }
636 
637 //===----------------------------------------------------------------------===//
638 // Code for LLVM::GEPOp.
639 //===----------------------------------------------------------------------===//
640 
641 constexpr int32_t GEPOp::kDynamicIndex;
642 
644  return GEPIndicesAdaptor<ValueRange>(getRawConstantIndicesAttr(),
645  getDynamicIndices());
646 }
647 
648 /// Returns the elemental type of any LLVM-compatible vector type or self.
650  if (auto vectorType = llvm::dyn_cast<VectorType>(type))
651  return vectorType.getElementType();
652  return type;
653 }
654 
655 /// Destructures the 'indices' parameter into 'rawConstantIndices' and
656 /// 'dynamicIndices', encoding the former in the process. In the process,
657 /// dynamic indices which are used to index into a structure type are converted
658 /// to constant indices when possible. To do this, the GEPs element type should
659 /// be passed as first parameter.
660 static void destructureIndices(Type currType, ArrayRef<GEPArg> indices,
661  SmallVectorImpl<int32_t> &rawConstantIndices,
662  SmallVectorImpl<Value> &dynamicIndices) {
663  for (const GEPArg &iter : indices) {
664  // If the thing we are currently indexing into is a struct we must turn
665  // any integer constants into constant indices. If this is not possible
666  // we don't do anything here. The verifier will catch it and emit a proper
667  // error. All other canonicalization is done in the fold method.
668  bool requiresConst = !rawConstantIndices.empty() &&
669  isa_and_nonnull<LLVMStructType>(currType);
670  if (Value val = llvm::dyn_cast_if_present<Value>(iter)) {
671  APInt intC;
672  if (requiresConst && matchPattern(val, m_ConstantInt(&intC)) &&
673  intC.isSignedIntN(kGEPConstantBitWidth)) {
674  rawConstantIndices.push_back(intC.getSExtValue());
675  } else {
676  rawConstantIndices.push_back(GEPOp::kDynamicIndex);
677  dynamicIndices.push_back(val);
678  }
679  } else {
680  rawConstantIndices.push_back(cast<GEPConstantIndex>(iter));
681  }
682 
683  // Skip for very first iteration of this loop. First index does not index
684  // within the aggregates, but is just a pointer offset.
685  if (rawConstantIndices.size() == 1 || !currType)
686  continue;
687 
688  currType = TypeSwitch<Type, Type>(currType)
689  .Case<VectorType, LLVMArrayType>([](auto containerType) {
690  return containerType.getElementType();
691  })
692  .Case([&](LLVMStructType structType) -> Type {
693  int64_t memberIndex = rawConstantIndices.back();
694  if (memberIndex >= 0 && static_cast<size_t>(memberIndex) <
695  structType.getBody().size())
696  return structType.getBody()[memberIndex];
697  return nullptr;
698  })
699  .Default(Type(nullptr));
700  }
701 }
702 
703 void GEPOp::build(OpBuilder &builder, OperationState &result, Type resultType,
704  Type elementType, Value basePtr, ArrayRef<GEPArg> indices,
705  GEPNoWrapFlags noWrapFlags,
706  ArrayRef<NamedAttribute> attributes) {
707  SmallVector<int32_t> rawConstantIndices;
708  SmallVector<Value> dynamicIndices;
709  destructureIndices(elementType, indices, rawConstantIndices, dynamicIndices);
710 
711  result.addTypes(resultType);
712  result.addAttributes(attributes);
713  result.getOrAddProperties<Properties>().rawConstantIndices =
714  builder.getDenseI32ArrayAttr(rawConstantIndices);
715  result.getOrAddProperties<Properties>().noWrapFlags = noWrapFlags;
716  result.getOrAddProperties<Properties>().elem_type =
717  TypeAttr::get(elementType);
718  result.addOperands(basePtr);
719  result.addOperands(dynamicIndices);
720 }
721 
722 void GEPOp::build(OpBuilder &builder, OperationState &result, Type resultType,
723  Type elementType, Value basePtr, ValueRange indices,
724  GEPNoWrapFlags noWrapFlags,
725  ArrayRef<NamedAttribute> attributes) {
726  build(builder, result, resultType, elementType, basePtr,
727  SmallVector<GEPArg>(indices), noWrapFlags, attributes);
728 }
729 
730 static ParseResult
733  DenseI32ArrayAttr &rawConstantIndices) {
734  SmallVector<int32_t> constantIndices;
735 
736  auto idxParser = [&]() -> ParseResult {
737  int32_t constantIndex;
738  OptionalParseResult parsedInteger =
740  if (parsedInteger.has_value()) {
741  if (failed(parsedInteger.value()))
742  return failure();
743  constantIndices.push_back(constantIndex);
744  return success();
745  }
746 
747  constantIndices.push_back(LLVM::GEPOp::kDynamicIndex);
748  return parser.parseOperand(indices.emplace_back());
749  };
750  if (parser.parseCommaSeparatedList(idxParser))
751  return failure();
752 
753  rawConstantIndices =
754  DenseI32ArrayAttr::get(parser.getContext(), constantIndices);
755  return success();
756 }
757 
758 static void printGEPIndices(OpAsmPrinter &printer, LLVM::GEPOp gepOp,
759  OperandRange indices,
760  DenseI32ArrayAttr rawConstantIndices) {
761  llvm::interleaveComma(
762  GEPIndicesAdaptor<OperandRange>(rawConstantIndices, indices), printer,
764  if (Value val = llvm::dyn_cast_if_present<Value>(cst))
765  printer.printOperand(val);
766  else
767  printer << cast<IntegerAttr>(cst).getInt();
768  });
769 }
770 
771 /// For the given `indices`, check if they comply with `baseGEPType`,
772 /// especially check against LLVMStructTypes nested within.
773 static LogicalResult
774 verifyStructIndices(Type baseGEPType, unsigned indexPos,
776  function_ref<InFlightDiagnostic()> emitOpError) {
777  if (indexPos >= indices.size())
778  // Stop searching
779  return success();
780 
781  return TypeSwitch<Type, LogicalResult>(baseGEPType)
782  .Case<LLVMStructType>([&](LLVMStructType structType) -> LogicalResult {
783  auto attr = dyn_cast<IntegerAttr>(indices[indexPos]);
784  if (!attr)
785  return emitOpError() << "expected index " << indexPos
786  << " indexing a struct to be constant";
787 
788  int32_t gepIndex = attr.getInt();
789  ArrayRef<Type> elementTypes = structType.getBody();
790  if (gepIndex < 0 ||
791  static_cast<size_t>(gepIndex) >= elementTypes.size())
792  return emitOpError() << "index " << indexPos
793  << " indexing a struct is out of bounds";
794 
795  // Instead of recursively going into every children types, we only
796  // dive into the one indexed by gepIndex.
797  return verifyStructIndices(elementTypes[gepIndex], indexPos + 1,
798  indices, emitOpError);
799  })
800  .Case<VectorType, LLVMArrayType>(
801  [&](auto containerType) -> LogicalResult {
802  return verifyStructIndices(containerType.getElementType(),
803  indexPos + 1, indices, emitOpError);
804  })
805  .Default([&](auto otherType) -> LogicalResult {
806  return emitOpError()
807  << "type " << otherType << " cannot be indexed (index #"
808  << indexPos << ")";
809  });
810 }
811 
812 /// Driver function around `verifyStructIndices`.
813 static LogicalResult
815  function_ref<InFlightDiagnostic()> emitOpError) {
816  return verifyStructIndices(baseGEPType, /*indexPos=*/1, indices, emitOpError);
817 }
818 
819 LogicalResult LLVM::GEPOp::verify() {
820  if (static_cast<size_t>(
821  llvm::count(getRawConstantIndices(), kDynamicIndex)) !=
822  getDynamicIndices().size())
823  return emitOpError("expected as many dynamic indices as specified in '")
824  << getRawConstantIndicesAttrName().getValue() << "'";
825 
826  if (getNoWrapFlags() == GEPNoWrapFlags::inboundsFlag)
827  return emitOpError("'inbounds_flag' cannot be used directly.");
828 
829  return verifyStructIndices(getElemType(), getIndices(),
830  [&] { return emitOpError(); });
831 }
832 
833 //===----------------------------------------------------------------------===//
834 // LoadOp
835 //===----------------------------------------------------------------------===//
836 
837 void LoadOp::getEffects(
839  &effects) {
840  effects.emplace_back(MemoryEffects::Read::get(), &getAddrMutable());
841  // Volatile operations can have target-specific read-write effects on
842  // memory besides the one referred to by the pointer operand.
843  // Similarly, atomic operations that are monotonic or stricter cause
844  // synchronization that from a language point-of-view, are arbitrary
845  // read-writes into memory.
846  if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
847  getOrdering() != AtomicOrdering::unordered)) {
848  effects.emplace_back(MemoryEffects::Write::get());
849  effects.emplace_back(MemoryEffects::Read::get());
850  }
851 }
852 
853 /// Returns true if the given type is supported by atomic operations. All
854 /// integer, float, and pointer types with a power-of-two bitsize and a minimal
855 /// size of 8 bits are supported.
857  const DataLayout &dataLayout) {
858  if (!isa<IntegerType, LLVMPointerType>(type))
860  return false;
861 
862  llvm::TypeSize bitWidth = dataLayout.getTypeSizeInBits(type);
863  if (bitWidth.isScalable())
864  return false;
865  // Needs to be at least 8 bits and a power of two.
866  return bitWidth >= 8 && (bitWidth & (bitWidth - 1)) == 0;
867 }
868 
869 /// Verifies the attributes and the type of atomic memory access operations.
870 template <typename OpTy>
871 static LogicalResult
872 verifyAtomicMemOp(OpTy memOp, Type valueType,
873  ArrayRef<AtomicOrdering> unsupportedOrderings) {
874  if (memOp.getOrdering() != AtomicOrdering::not_atomic) {
875  DataLayout dataLayout = DataLayout::closest(memOp);
876  if (!isTypeCompatibleWithAtomicOp(valueType, dataLayout))
877  return memOp.emitOpError("unsupported type ")
878  << valueType << " for atomic access";
879  if (llvm::is_contained(unsupportedOrderings, memOp.getOrdering()))
880  return memOp.emitOpError("unsupported ordering '")
881  << stringifyAtomicOrdering(memOp.getOrdering()) << "'";
882  if (!memOp.getAlignment())
883  return memOp.emitOpError("expected alignment for atomic access");
884  return success();
885  }
886  if (memOp.getSyncscope())
887  return memOp.emitOpError(
888  "expected syncscope to be null for non-atomic access");
889  return success();
890 }
891 
892 LogicalResult LoadOp::verify() {
893  Type valueType = getResult().getType();
894  return verifyAtomicMemOp(*this, valueType,
895  {AtomicOrdering::release, AtomicOrdering::acq_rel});
896 }
897 
898 void LoadOp::build(OpBuilder &builder, OperationState &state, Type type,
899  Value addr, unsigned alignment, bool isVolatile,
900  bool isNonTemporal, bool isInvariant, bool isInvariantGroup,
901  AtomicOrdering ordering, StringRef syncscope) {
902  build(builder, state, type, addr,
903  alignment ? builder.getI64IntegerAttr(alignment) : nullptr, isVolatile,
904  isNonTemporal, isInvariant, isInvariantGroup, ordering,
905  syncscope.empty() ? nullptr : builder.getStringAttr(syncscope),
906  /*dereferenceable=*/nullptr,
907  /*access_groups=*/nullptr,
908  /*alias_scopes=*/nullptr, /*noalias_scopes=*/nullptr,
909  /*tbaa=*/nullptr);
910 }
911 
912 //===----------------------------------------------------------------------===//
913 // StoreOp
914 //===----------------------------------------------------------------------===//
915 
916 void StoreOp::getEffects(
918  &effects) {
919  effects.emplace_back(MemoryEffects::Write::get(), &getAddrMutable());
920  // Volatile operations can have target-specific read-write effects on
921  // memory besides the one referred to by the pointer operand.
922  // Similarly, atomic operations that are monotonic or stricter cause
923  // synchronization that from a language point-of-view, are arbitrary
924  // read-writes into memory.
925  if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
926  getOrdering() != AtomicOrdering::unordered)) {
927  effects.emplace_back(MemoryEffects::Write::get());
928  effects.emplace_back(MemoryEffects::Read::get());
929  }
930 }
931 
932 LogicalResult StoreOp::verify() {
933  Type valueType = getValue().getType();
934  return verifyAtomicMemOp(*this, valueType,
935  {AtomicOrdering::acquire, AtomicOrdering::acq_rel});
936 }
937 
938 void StoreOp::build(OpBuilder &builder, OperationState &state, Value value,
939  Value addr, unsigned alignment, bool isVolatile,
940  bool isNonTemporal, bool isInvariantGroup,
941  AtomicOrdering ordering, StringRef syncscope) {
942  build(builder, state, value, addr,
943  alignment ? builder.getI64IntegerAttr(alignment) : nullptr, isVolatile,
944  isNonTemporal, isInvariantGroup, ordering,
945  syncscope.empty() ? nullptr : builder.getStringAttr(syncscope),
946  /*access_groups=*/nullptr,
947  /*alias_scopes=*/nullptr, /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr);
948 }
949 
950 //===----------------------------------------------------------------------===//
951 // CallOp
952 //===----------------------------------------------------------------------===//
953 
954 /// Gets the MLIR Op-like result types of a LLVMFunctionType.
955 static SmallVector<Type, 1> getCallOpResultTypes(LLVMFunctionType calleeType) {
956  SmallVector<Type, 1> results;
957  Type resultType = calleeType.getReturnType();
958  if (!isa<LLVM::LLVMVoidType>(resultType))
959  results.push_back(resultType);
960  return results;
961 }
962 
963 /// Gets the variadic callee type for a LLVMFunctionType.
964 static TypeAttr getCallOpVarCalleeType(LLVMFunctionType calleeType) {
965  return calleeType.isVarArg() ? TypeAttr::get(calleeType) : nullptr;
966 }
967 
968 /// Constructs a LLVMFunctionType from MLIR `results` and `args`.
969 static LLVMFunctionType getLLVMFuncType(MLIRContext *context, TypeRange results,
970  ValueRange args) {
971  Type resultType;
972  if (results.empty())
973  resultType = LLVMVoidType::get(context);
974  else
975  resultType = results.front();
976  return LLVMFunctionType::get(resultType, llvm::to_vector(args.getTypes()),
977  /*isVarArg=*/false);
978 }
979 
980 void CallOp::build(OpBuilder &builder, OperationState &state, TypeRange results,
981  StringRef callee, ValueRange args) {
982  build(builder, state, results, builder.getStringAttr(callee), args);
983 }
984 
985 void CallOp::build(OpBuilder &builder, OperationState &state, TypeRange results,
986  StringAttr callee, ValueRange args) {
987  build(builder, state, results, SymbolRefAttr::get(callee), args);
988 }
989 
990 void CallOp::build(OpBuilder &builder, OperationState &state, TypeRange results,
991  FlatSymbolRefAttr callee, ValueRange args) {
992  assert(callee && "expected non-null callee in direct call builder");
993  build(builder, state, results,
994  /*var_callee_type=*/nullptr, callee, args, /*fastmathFlags=*/nullptr,
995  /*CConv=*/nullptr, /*TailCallKind=*/nullptr,
996  /*memory_effects=*/nullptr,
997  /*convergent=*/nullptr, /*no_unwind=*/nullptr, /*will_return=*/nullptr,
998  /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{},
999  /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr,
1000  /*access_groups=*/nullptr, /*alias_scopes=*/nullptr,
1001  /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr,
1002  /*no_inline=*/nullptr, /*always_inline=*/nullptr,
1003  /*inline_hint=*/nullptr);
1004 }
1005 
1006 void CallOp::build(OpBuilder &builder, OperationState &state,
1007  LLVMFunctionType calleeType, StringRef callee,
1008  ValueRange args) {
1009  build(builder, state, calleeType, builder.getStringAttr(callee), args);
1010 }
1011 
1012 void CallOp::build(OpBuilder &builder, OperationState &state,
1013  LLVMFunctionType calleeType, StringAttr callee,
1014  ValueRange args) {
1015  build(builder, state, calleeType, SymbolRefAttr::get(callee), args);
1016 }
1017 
1018 void CallOp::build(OpBuilder &builder, OperationState &state,
1019  LLVMFunctionType calleeType, FlatSymbolRefAttr callee,
1020  ValueRange args) {
1021  build(builder, state, getCallOpResultTypes(calleeType),
1022  getCallOpVarCalleeType(calleeType), callee, args,
1023  /*fastmathFlags=*/nullptr,
1024  /*CConv=*/nullptr,
1025  /*TailCallKind=*/nullptr, /*memory_effects=*/nullptr,
1026  /*convergent=*/nullptr,
1027  /*no_unwind=*/nullptr, /*will_return=*/nullptr,
1028  /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{},
1029  /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr,
1030  /*access_groups=*/nullptr,
1031  /*alias_scopes=*/nullptr, /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr,
1032  /*no_inline=*/nullptr, /*always_inline=*/nullptr,
1033  /*inline_hint=*/nullptr);
1034 }
1035 
1036 void CallOp::build(OpBuilder &builder, OperationState &state,
1037  LLVMFunctionType calleeType, ValueRange args) {
1038  build(builder, state, getCallOpResultTypes(calleeType),
1039  getCallOpVarCalleeType(calleeType),
1040  /*callee=*/nullptr, args,
1041  /*fastmathFlags=*/nullptr,
1042  /*CConv=*/nullptr, /*TailCallKind=*/nullptr, /*memory_effects=*/nullptr,
1043  /*convergent=*/nullptr, /*no_unwind=*/nullptr, /*will_return=*/nullptr,
1044  /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{},
1045  /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr,
1046  /*access_groups=*/nullptr, /*alias_scopes=*/nullptr,
1047  /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr,
1048  /*no_inline=*/nullptr, /*always_inline=*/nullptr,
1049  /*inline_hint=*/nullptr);
1050 }
1051 
1052 void CallOp::build(OpBuilder &builder, OperationState &state, LLVMFuncOp func,
1053  ValueRange args) {
1054  auto calleeType = func.getFunctionType();
1055  build(builder, state, getCallOpResultTypes(calleeType),
1056  getCallOpVarCalleeType(calleeType), SymbolRefAttr::get(func), args,
1057  /*fastmathFlags=*/nullptr,
1058  /*CConv=*/nullptr, /*TailCallKind=*/nullptr, /*memory_effects=*/nullptr,
1059  /*convergent=*/nullptr, /*no_unwind=*/nullptr, /*will_return=*/nullptr,
1060  /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{},
1061  /*access_groups=*/nullptr, /*alias_scopes=*/nullptr,
1062  /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr,
1063  /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr,
1064  /*no_inline=*/nullptr, /*always_inline=*/nullptr,
1065  /*inline_hint=*/nullptr);
1066 }
1067 
1068 CallInterfaceCallable CallOp::getCallableForCallee() {
1069  // Direct call.
1070  if (FlatSymbolRefAttr calleeAttr = getCalleeAttr())
1071  return calleeAttr;
1072  // Indirect call, callee Value is the first operand.
1073  return getOperand(0);
1074 }
1075 
1076 void CallOp::setCalleeFromCallable(CallInterfaceCallable callee) {
1077  // Direct call.
1078  if (FlatSymbolRefAttr calleeAttr = getCalleeAttr()) {
1079  auto symRef = cast<SymbolRefAttr>(callee);
1080  return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1081  }
1082  // Indirect call, callee Value is the first operand.
1083  return setOperand(0, cast<Value>(callee));
1084 }
1085 
1086 Operation::operand_range CallOp::getArgOperands() {
1087  return getCalleeOperands().drop_front(getCallee().has_value() ? 0 : 1);
1088 }
1089 
1090 MutableOperandRange CallOp::getArgOperandsMutable() {
1091  return MutableOperandRange(*this, getCallee().has_value() ? 0 : 1,
1092  getCalleeOperands().size());
1093 }
1094 
1095 /// Verify that an inlinable callsite of a debug-info-bearing function in a
1096 /// debug-info-bearing function has a debug location attached to it. This
1097 /// mirrors an LLVM IR verifier.
1098 static LogicalResult verifyCallOpDebugInfo(CallOp callOp, LLVMFuncOp callee) {
1099  if (callee.isExternal())
1100  return success();
1101  auto parentFunc = callOp->getParentOfType<FunctionOpInterface>();
1102  if (!parentFunc)
1103  return success();
1104 
1105  auto hasSubprogram = [](Operation *op) {
1106  return op->getLoc()
1107  ->findInstanceOf<FusedLocWith<LLVM::DISubprogramAttr>>() !=
1108  nullptr;
1109  };
1110  if (!hasSubprogram(parentFunc) || !hasSubprogram(callee))
1111  return success();
1112  bool containsLoc = !isa<UnknownLoc>(callOp->getLoc());
1113  if (!containsLoc)
1114  return callOp.emitError()
1115  << "inlinable function call in a function with a DISubprogram "
1116  "location must have a debug location";
1117  return success();
1118 }
1119 
1120 /// Verify that the parameter and return types of the variadic callee type match
1121 /// the `callOp` argument and result types.
1122 template <typename OpTy>
1123 static LogicalResult verifyCallOpVarCalleeType(OpTy callOp) {
1124  std::optional<LLVMFunctionType> varCalleeType = callOp.getVarCalleeType();
1125  if (!varCalleeType)
1126  return success();
1127 
1128  // Verify the variadic callee type is a variadic function type.
1129  if (!varCalleeType->isVarArg())
1130  return callOp.emitOpError(
1131  "expected var_callee_type to be a variadic function type");
1132 
1133  // Verify the variadic callee type has at most as many parameters as the call
1134  // has argument operands.
1135  if (varCalleeType->getNumParams() > callOp.getArgOperands().size())
1136  return callOp.emitOpError("expected var_callee_type to have at most ")
1137  << callOp.getArgOperands().size() << " parameters";
1138 
1139  // Verify the variadic callee type matches the call argument types.
1140  for (auto [paramType, operand] :
1141  llvm::zip(varCalleeType->getParams(), callOp.getArgOperands()))
1142  if (paramType != operand.getType())
1143  return callOp.emitOpError()
1144  << "var_callee_type parameter type mismatch: " << paramType
1145  << " != " << operand.getType();
1146 
1147  // Verify the variadic callee type matches the call result type.
1148  if (!callOp.getNumResults()) {
1149  if (!isa<LLVMVoidType>(varCalleeType->getReturnType()))
1150  return callOp.emitOpError("expected var_callee_type to return void");
1151  } else {
1152  if (callOp.getResult().getType() != varCalleeType->getReturnType())
1153  return callOp.emitOpError("var_callee_type return type mismatch: ")
1154  << varCalleeType->getReturnType()
1155  << " != " << callOp.getResult().getType();
1156  }
1157  return success();
1158 }
1159 
1160 template <typename OpType>
1161 static LogicalResult verifyOperandBundles(OpType &op) {
1162  OperandRangeRange opBundleOperands = op.getOpBundleOperands();
1163  std::optional<ArrayAttr> opBundleTags = op.getOpBundleTags();
1164 
1165  auto isStringAttr = [](Attribute tagAttr) {
1166  return isa<StringAttr>(tagAttr);
1167  };
1168  if (opBundleTags && !llvm::all_of(*opBundleTags, isStringAttr))
1169  return op.emitError("operand bundle tag must be a StringAttr");
1170 
1171  size_t numOpBundles = opBundleOperands.size();
1172  size_t numOpBundleTags = opBundleTags ? opBundleTags->size() : 0;
1173  if (numOpBundles != numOpBundleTags)
1174  return op.emitError("expected ")
1175  << numOpBundles << " operand bundle tags, but actually got "
1176  << numOpBundleTags;
1177 
1178  return success();
1179 }
1180 
1181 LogicalResult CallOp::verify() { return verifyOperandBundles(*this); }
1182 
1183 LogicalResult CallOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
1184  if (failed(verifyCallOpVarCalleeType(*this)))
1185  return failure();
1186 
1187  // Type for the callee, we'll get it differently depending if it is a direct
1188  // or indirect call.
1189  Type fnType;
1190 
1191  bool isIndirect = false;
1192 
1193  // If this is an indirect call, the callee attribute is missing.
1194  FlatSymbolRefAttr calleeName = getCalleeAttr();
1195  if (!calleeName) {
1196  isIndirect = true;
1197  if (!getNumOperands())
1198  return emitOpError(
1199  "must have either a `callee` attribute or at least an operand");
1200  auto ptrType = llvm::dyn_cast<LLVMPointerType>(getOperand(0).getType());
1201  if (!ptrType)
1202  return emitOpError("indirect call expects a pointer as callee: ")
1203  << getOperand(0).getType();
1204 
1205  return success();
1206  } else {
1207  Operation *callee =
1208  symbolTable.lookupNearestSymbolFrom(*this, calleeName.getAttr());
1209  if (!callee)
1210  return emitOpError()
1211  << "'" << calleeName.getValue()
1212  << "' does not reference a symbol in the current scope";
1213  if (auto fn = dyn_cast<LLVMFuncOp>(callee)) {
1214  if (failed(verifyCallOpDebugInfo(*this, fn)))
1215  return failure();
1216  fnType = fn.getFunctionType();
1217  } else if (auto ifunc = dyn_cast<IFuncOp>(callee)) {
1218  fnType = ifunc.getIFuncType();
1219  } else {
1220  return emitOpError()
1221  << "'" << calleeName.getValue()
1222  << "' does not reference a valid LLVM function or IFunc";
1223  }
1224  }
1225 
1226  LLVMFunctionType funcType = llvm::dyn_cast<LLVMFunctionType>(fnType);
1227  if (!funcType)
1228  return emitOpError("callee does not have a functional type: ") << fnType;
1229 
1230  if (funcType.isVarArg() && !getVarCalleeType())
1231  return emitOpError() << "missing var_callee_type attribute for vararg call";
1232 
1233  // Verify that the operand and result types match the callee.
1234 
1235  if (!funcType.isVarArg() &&
1236  funcType.getNumParams() != (getCalleeOperands().size() - isIndirect))
1237  return emitOpError() << "incorrect number of operands ("
1238  << (getCalleeOperands().size() - isIndirect)
1239  << ") for callee (expecting: "
1240  << funcType.getNumParams() << ")";
1241 
1242  if (funcType.getNumParams() > (getCalleeOperands().size() - isIndirect))
1243  return emitOpError() << "incorrect number of operands ("
1244  << (getCalleeOperands().size() - isIndirect)
1245  << ") for varargs callee (expecting at least: "
1246  << funcType.getNumParams() << ")";
1247 
1248  for (unsigned i = 0, e = funcType.getNumParams(); i != e; ++i)
1249  if (getOperand(i + isIndirect).getType() != funcType.getParamType(i))
1250  return emitOpError() << "operand type mismatch for operand " << i << ": "
1251  << getOperand(i + isIndirect).getType()
1252  << " != " << funcType.getParamType(i);
1253 
1254  if (getNumResults() == 0 &&
1255  !llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1256  return emitOpError() << "expected function call to produce a value";
1257 
1258  if (getNumResults() != 0 &&
1259  llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1260  return emitOpError()
1261  << "calling function with void result must not produce values";
1262 
1263  if (getNumResults() > 1)
1264  return emitOpError()
1265  << "expected LLVM function call to produce 0 or 1 result";
1266 
1267  if (getNumResults() && getResult().getType() != funcType.getReturnType())
1268  return emitOpError() << "result type mismatch: " << getResult().getType()
1269  << " != " << funcType.getReturnType();
1270 
1271  return success();
1272 }
1273 
1274 void CallOp::print(OpAsmPrinter &p) {
1275  auto callee = getCallee();
1276  bool isDirect = callee.has_value();
1277 
1278  p << ' ';
1279 
1280  // Print calling convention.
1281  if (getCConv() != LLVM::CConv::C)
1282  p << stringifyCConv(getCConv()) << ' ';
1283 
1284  if (getTailCallKind() != LLVM::TailCallKind::None)
1285  p << tailcallkind::stringifyTailCallKind(getTailCallKind()) << ' ';
1286 
1287  // Print the direct callee if present as a function attribute, or an indirect
1288  // callee (first operand) otherwise.
1289  if (isDirect)
1290  p.printSymbolName(callee.value());
1291  else
1292  p << getOperand(0);
1293 
1294  auto args = getCalleeOperands().drop_front(isDirect ? 0 : 1);
1295  p << '(' << args << ')';
1296 
1297  // Print the variadic callee type if the call is variadic.
1298  if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1299  p << " vararg(" << *varCalleeType << ")";
1300 
1301  if (!getOpBundleOperands().empty()) {
1302  p << " ";
1303  printOpBundles(p, *this, getOpBundleOperands(),
1304  getOpBundleOperands().getTypes(), getOpBundleTags());
1305  }
1306 
1307  p.printOptionalAttrDict(processFMFAttr((*this)->getAttrs()),
1308  {getCalleeAttrName(), getTailCallKindAttrName(),
1309  getVarCalleeTypeAttrName(), getCConvAttrName(),
1310  getOperandSegmentSizesAttrName(),
1311  getOpBundleSizesAttrName(),
1312  getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1313  getResAttrsAttrName()});
1314 
1315  p << " : ";
1316  if (!isDirect)
1317  p << getOperand(0).getType() << ", ";
1318 
1319  // Reconstruct the MLIR function type from operand and result types.
1321  p, args.getTypes(), getArgAttrsAttr(),
1322  /*isVariadic=*/false, getResultTypes(), getResAttrsAttr());
1323 }
1324 
1325 /// Parses the type of a call operation and resolves the operands if the parsing
1326 /// succeeds. Returns failure otherwise.
1328  OpAsmParser &parser, OperationState &result, bool isDirect,
1331  SmallVectorImpl<DictionaryAttr> &resultAttrs) {
1332  SMLoc trailingTypesLoc = parser.getCurrentLocation();
1333  SmallVector<Type> types;
1334  if (parser.parseColon())
1335  return failure();
1336  if (!isDirect) {
1337  types.emplace_back();
1338  if (parser.parseType(types.back()))
1339  return failure();
1340  if (parser.parseOptionalComma())
1341  return parser.emitError(
1342  trailingTypesLoc, "expected indirect call to have 2 trailing types");
1343  }
1344  SmallVector<Type> argTypes;
1345  SmallVector<Type> resTypes;
1346  if (call_interface_impl::parseFunctionSignature(parser, argTypes, argAttrs,
1347  resTypes, resultAttrs)) {
1348  if (isDirect)
1349  return parser.emitError(trailingTypesLoc,
1350  "expected direct call to have 1 trailing types");
1351  return parser.emitError(trailingTypesLoc,
1352  "expected trailing function type");
1353  }
1354 
1355  if (resTypes.size() > 1)
1356  return parser.emitError(trailingTypesLoc,
1357  "expected function with 0 or 1 result");
1358  if (resTypes.size() == 1 && llvm::isa<LLVM::LLVMVoidType>(resTypes[0]))
1359  return parser.emitError(trailingTypesLoc,
1360  "expected a non-void result type");
1361 
1362  // The head element of the types list matches the callee type for
1363  // indirect calls, while the types list is emtpy for direct calls.
1364  // Append the function input types to resolve the call operation
1365  // operands.
1366  llvm::append_range(types, argTypes);
1367  if (parser.resolveOperands(operands, types, parser.getNameLoc(),
1368  result.operands))
1369  return failure();
1370  if (resTypes.size() != 0)
1371  result.addTypes(resTypes);
1372 
1373  return success();
1374 }
1375 
1376 /// Parses an optional function pointer operand before the call argument list
1377 /// for indirect calls, or stops parsing at the function identifier otherwise.
1378 static ParseResult parseOptionalCallFuncPtr(
1379  OpAsmParser &parser,
1381  OpAsmParser::UnresolvedOperand funcPtrOperand;
1382  OptionalParseResult parseResult = parser.parseOptionalOperand(funcPtrOperand);
1383  if (parseResult.has_value()) {
1384  if (failed(*parseResult))
1385  return *parseResult;
1386  operands.push_back(funcPtrOperand);
1387  }
1388  return success();
1389 }
1390 
1391 static ParseResult resolveOpBundleOperands(
1392  OpAsmParser &parser, SMLoc loc, OperationState &state,
1394  ArrayRef<SmallVector<Type>> opBundleOperandTypes,
1395  StringAttr opBundleSizesAttrName) {
1396  unsigned opBundleIndex = 0;
1397  for (const auto &[operands, types] :
1398  llvm::zip_equal(opBundleOperands, opBundleOperandTypes)) {
1399  if (operands.size() != types.size())
1400  return parser.emitError(loc, "expected ")
1401  << operands.size()
1402  << " types for operand bundle operands for operand bundle #"
1403  << opBundleIndex << ", but actually got " << types.size();
1404  if (parser.resolveOperands(operands, types, loc, state.operands))
1405  return failure();
1406  }
1407 
1408  SmallVector<int32_t> opBundleSizes;
1409  opBundleSizes.reserve(opBundleOperands.size());
1410  for (const auto &operands : opBundleOperands)
1411  opBundleSizes.push_back(operands.size());
1412 
1413  state.addAttribute(
1414  opBundleSizesAttrName,
1415  DenseI32ArrayAttr::get(parser.getContext(), opBundleSizes));
1416 
1417  return success();
1418 }
1419 
1420 // <operation> ::= `llvm.call` (cconv)? (tailcallkind)? (function-id | ssa-use)
1421 // `(` ssa-use-list `)`
1422 // ( `vararg(` var-callee-type `)` )?
1423 // ( `[` op-bundles-list `]` )?
1424 // attribute-dict? `:` (type `,`)? function-type
1425 ParseResult CallOp::parse(OpAsmParser &parser, OperationState &result) {
1426  SymbolRefAttr funcAttr;
1427  TypeAttr varCalleeType;
1430  SmallVector<SmallVector<Type>> opBundleOperandTypes;
1431  ArrayAttr opBundleTags;
1432 
1433  // Default to C Calling Convention if no keyword is provided.
1434  result.addAttribute(
1435  getCConvAttrName(result.name),
1436  CConvAttr::get(parser.getContext(),
1437  parseOptionalLLVMKeyword<CConv>(parser, LLVM::CConv::C)));
1438 
1439  result.addAttribute(
1440  getTailCallKindAttrName(result.name),
1442  parseOptionalLLVMKeyword<TailCallKind>(
1443  parser, LLVM::TailCallKind::None)));
1444 
1445  // Parse a function pointer for indirect calls.
1446  if (parseOptionalCallFuncPtr(parser, operands))
1447  return failure();
1448  bool isDirect = operands.empty();
1449 
1450  // Parse a function identifier for direct calls.
1451  if (isDirect)
1452  if (parser.parseAttribute(funcAttr, "callee", result.attributes))
1453  return failure();
1454 
1455  // Parse the function arguments.
1456  if (parser.parseOperandList(operands, OpAsmParser::Delimiter::Paren))
1457  return failure();
1458 
1459  bool isVarArg = parser.parseOptionalKeyword("vararg").succeeded();
1460  if (isVarArg) {
1461  StringAttr varCalleeTypeAttrName =
1462  CallOp::getVarCalleeTypeAttrName(result.name);
1463  if (parser.parseLParen().failed() ||
1464  parser
1465  .parseAttribute(varCalleeType, varCalleeTypeAttrName,
1466  result.attributes)
1467  .failed() ||
1468  parser.parseRParen().failed())
1469  return failure();
1470  }
1471 
1472  SMLoc opBundlesLoc = parser.getCurrentLocation();
1473  if (std::optional<ParseResult> result = parseOpBundles(
1474  parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1475  result && failed(*result))
1476  return failure();
1477  if (opBundleTags && !opBundleTags.empty())
1478  result.addAttribute(CallOp::getOpBundleTagsAttrName(result.name).getValue(),
1479  opBundleTags);
1480 
1481  if (parser.parseOptionalAttrDict(result.attributes))
1482  return failure();
1483 
1484  // Parse the trailing type list and resolve the operands.
1485  SmallVector<DictionaryAttr> argAttrs;
1486  SmallVector<DictionaryAttr> resultAttrs;
1487  if (parseCallTypeAndResolveOperands(parser, result, isDirect, operands,
1488  argAttrs, resultAttrs))
1489  return failure();
1491  parser.getBuilder(), result, argAttrs, resultAttrs,
1492  getArgAttrsAttrName(result.name), getResAttrsAttrName(result.name));
1493  if (resolveOpBundleOperands(parser, opBundlesLoc, result, opBundleOperands,
1494  opBundleOperandTypes,
1495  getOpBundleSizesAttrName(result.name)))
1496  return failure();
1497 
1498  int32_t numOpBundleOperands = 0;
1499  for (const auto &operands : opBundleOperands)
1500  numOpBundleOperands += operands.size();
1501 
1502  result.addAttribute(
1503  CallOp::getOperandSegmentSizeAttr(),
1505  {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
1506  return success();
1507 }
1508 
1509 LLVMFunctionType CallOp::getCalleeFunctionType() {
1510  if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1511  return *varCalleeType;
1512  return getLLVMFuncType(getContext(), getResultTypes(), getArgOperands());
1513 }
1514 
1515 ///===---------------------------------------------------------------------===//
1516 /// LLVM::InvokeOp
1517 ///===---------------------------------------------------------------------===//
1518 
1519 void InvokeOp::build(OpBuilder &builder, OperationState &state, LLVMFuncOp func,
1520  ValueRange ops, Block *normal, ValueRange normalOps,
1521  Block *unwind, ValueRange unwindOps) {
1522  auto calleeType = func.getFunctionType();
1523  build(builder, state, getCallOpResultTypes(calleeType),
1524  getCallOpVarCalleeType(calleeType), SymbolRefAttr::get(func), ops,
1525  /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr, normalOps, unwindOps,
1526  nullptr, nullptr, {}, {}, normal, unwind);
1527 }
1528 
1529 void InvokeOp::build(OpBuilder &builder, OperationState &state, TypeRange tys,
1530  FlatSymbolRefAttr callee, ValueRange ops, Block *normal,
1531  ValueRange normalOps, Block *unwind,
1532  ValueRange unwindOps) {
1533  build(builder, state, tys,
1534  /*var_callee_type=*/nullptr, callee, ops, /*arg_attrs=*/nullptr,
1535  /*res_attrs=*/nullptr, normalOps, unwindOps, nullptr, nullptr, {}, {},
1536  normal, unwind);
1537 }
1538 
1539 void InvokeOp::build(OpBuilder &builder, OperationState &state,
1540  LLVMFunctionType calleeType, FlatSymbolRefAttr callee,
1541  ValueRange ops, Block *normal, ValueRange normalOps,
1542  Block *unwind, ValueRange unwindOps) {
1543  build(builder, state, getCallOpResultTypes(calleeType),
1544  getCallOpVarCalleeType(calleeType), callee, ops,
1545  /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr, normalOps, unwindOps,
1546  nullptr, nullptr, {}, {}, normal, unwind);
1547 }
1548 
1550  assert(index < getNumSuccessors() && "invalid successor index");
1551  return SuccessorOperands(index == 0 ? getNormalDestOperandsMutable()
1552  : getUnwindDestOperandsMutable());
1553 }
1554 
1555 CallInterfaceCallable InvokeOp::getCallableForCallee() {
1556  // Direct call.
1557  if (FlatSymbolRefAttr calleeAttr = getCalleeAttr())
1558  return calleeAttr;
1559  // Indirect call, callee Value is the first operand.
1560  return getOperand(0);
1561 }
1562 
1563 void InvokeOp::setCalleeFromCallable(CallInterfaceCallable callee) {
1564  // Direct call.
1565  if (FlatSymbolRefAttr calleeAttr = getCalleeAttr()) {
1566  auto symRef = cast<SymbolRefAttr>(callee);
1567  return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1568  }
1569  // Indirect call, callee Value is the first operand.
1570  return setOperand(0, cast<Value>(callee));
1571 }
1572 
1573 Operation::operand_range InvokeOp::getArgOperands() {
1574  return getCalleeOperands().drop_front(getCallee().has_value() ? 0 : 1);
1575 }
1576 
1577 MutableOperandRange InvokeOp::getArgOperandsMutable() {
1578  return MutableOperandRange(*this, getCallee().has_value() ? 0 : 1,
1579  getCalleeOperands().size());
1580 }
1581 
1582 LogicalResult InvokeOp::verify() {
1583  if (failed(verifyCallOpVarCalleeType(*this)))
1584  return failure();
1585 
1586  Block *unwindDest = getUnwindDest();
1587  if (unwindDest->empty())
1588  return emitError("must have at least one operation in unwind destination");
1589 
1590  // In unwind destination, first operation must be LandingpadOp
1591  if (!isa<LandingpadOp>(unwindDest->front()))
1592  return emitError("first operation in unwind destination should be a "
1593  "llvm.landingpad operation");
1594 
1595  if (failed(verifyOperandBundles(*this)))
1596  return failure();
1597 
1598  return success();
1599 }
1600 
1601 void InvokeOp::print(OpAsmPrinter &p) {
1602  auto callee = getCallee();
1603  bool isDirect = callee.has_value();
1604 
1605  p << ' ';
1606 
1607  // Print calling convention.
1608  if (getCConv() != LLVM::CConv::C)
1609  p << stringifyCConv(getCConv()) << ' ';
1610 
1611  // Either function name or pointer
1612  if (isDirect)
1613  p.printSymbolName(callee.value());
1614  else
1615  p << getOperand(0);
1616 
1617  p << '(' << getCalleeOperands().drop_front(isDirect ? 0 : 1) << ')';
1618  p << " to ";
1619  p.printSuccessorAndUseList(getNormalDest(), getNormalDestOperands());
1620  p << " unwind ";
1621  p.printSuccessorAndUseList(getUnwindDest(), getUnwindDestOperands());
1622 
1623  // Print the variadic callee type if the invoke is variadic.
1624  if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1625  p << " vararg(" << *varCalleeType << ")";
1626 
1627  if (!getOpBundleOperands().empty()) {
1628  p << " ";
1629  printOpBundles(p, *this, getOpBundleOperands(),
1630  getOpBundleOperands().getTypes(), getOpBundleTags());
1631  }
1632 
1633  p.printOptionalAttrDict((*this)->getAttrs(),
1634  {getCalleeAttrName(), getOperandSegmentSizeAttr(),
1635  getCConvAttrName(), getVarCalleeTypeAttrName(),
1636  getOpBundleSizesAttrName(),
1637  getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1638  getResAttrsAttrName()});
1639 
1640  p << " : ";
1641  if (!isDirect)
1642  p << getOperand(0).getType() << ", ";
1644  p, getCalleeOperands().drop_front(isDirect ? 0 : 1).getTypes(),
1645  getArgAttrsAttr(),
1646  /*isVariadic=*/false, getResultTypes(), getResAttrsAttr());
1647 }
1648 
1649 // <operation> ::= `llvm.invoke` (cconv)? (function-id | ssa-use)
1650 // `(` ssa-use-list `)`
1651 // `to` bb-id (`[` ssa-use-and-type-list `]`)?
1652 // `unwind` bb-id (`[` ssa-use-and-type-list `]`)?
1653 // ( `vararg(` var-callee-type `)` )?
1654 // ( `[` op-bundles-list `]` )?
1655 // attribute-dict? `:` (type `,`)?
1656 // function-type-with-argument-attributes
1657 ParseResult InvokeOp::parse(OpAsmParser &parser, OperationState &result) {
1659  SymbolRefAttr funcAttr;
1660  TypeAttr varCalleeType;
1662  SmallVector<SmallVector<Type>> opBundleOperandTypes;
1663  ArrayAttr opBundleTags;
1664  Block *normalDest, *unwindDest;
1665  SmallVector<Value, 4> normalOperands, unwindOperands;
1666  Builder &builder = parser.getBuilder();
1667 
1668  // Default to C Calling Convention if no keyword is provided.
1669  result.addAttribute(
1670  getCConvAttrName(result.name),
1671  CConvAttr::get(parser.getContext(),
1672  parseOptionalLLVMKeyword<CConv>(parser, LLVM::CConv::C)));
1673 
1674  // Parse a function pointer for indirect calls.
1675  if (parseOptionalCallFuncPtr(parser, operands))
1676  return failure();
1677  bool isDirect = operands.empty();
1678 
1679  // Parse a function identifier for direct calls.
1680  if (isDirect && parser.parseAttribute(funcAttr, "callee", result.attributes))
1681  return failure();
1682 
1683  // Parse the function arguments.
1684  if (parser.parseOperandList(operands, OpAsmParser::Delimiter::Paren) ||
1685  parser.parseKeyword("to") ||
1686  parser.parseSuccessorAndUseList(normalDest, normalOperands) ||
1687  parser.parseKeyword("unwind") ||
1688  parser.parseSuccessorAndUseList(unwindDest, unwindOperands))
1689  return failure();
1690 
1691  bool isVarArg = parser.parseOptionalKeyword("vararg").succeeded();
1692  if (isVarArg) {
1693  StringAttr varCalleeTypeAttrName =
1694  InvokeOp::getVarCalleeTypeAttrName(result.name);
1695  if (parser.parseLParen().failed() ||
1696  parser
1697  .parseAttribute(varCalleeType, varCalleeTypeAttrName,
1698  result.attributes)
1699  .failed() ||
1700  parser.parseRParen().failed())
1701  return failure();
1702  }
1703 
1704  SMLoc opBundlesLoc = parser.getCurrentLocation();
1705  if (std::optional<ParseResult> result = parseOpBundles(
1706  parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1707  result && failed(*result))
1708  return failure();
1709  if (opBundleTags && !opBundleTags.empty())
1710  result.addAttribute(
1711  InvokeOp::getOpBundleTagsAttrName(result.name).getValue(),
1712  opBundleTags);
1713 
1714  if (parser.parseOptionalAttrDict(result.attributes))
1715  return failure();
1716 
1717  // Parse the trailing type list and resolve the function operands.
1718  SmallVector<DictionaryAttr> argAttrs;
1719  SmallVector<DictionaryAttr> resultAttrs;
1720  if (parseCallTypeAndResolveOperands(parser, result, isDirect, operands,
1721  argAttrs, resultAttrs))
1722  return failure();
1724  parser.getBuilder(), result, argAttrs, resultAttrs,
1725  getArgAttrsAttrName(result.name), getResAttrsAttrName(result.name));
1726 
1727  if (resolveOpBundleOperands(parser, opBundlesLoc, result, opBundleOperands,
1728  opBundleOperandTypes,
1729  getOpBundleSizesAttrName(result.name)))
1730  return failure();
1731 
1732  result.addSuccessors({normalDest, unwindDest});
1733  result.addOperands(normalOperands);
1734  result.addOperands(unwindOperands);
1735 
1736  int32_t numOpBundleOperands = 0;
1737  for (const auto &operands : opBundleOperands)
1738  numOpBundleOperands += operands.size();
1739 
1740  result.addAttribute(
1741  InvokeOp::getOperandSegmentSizeAttr(),
1742  builder.getDenseI32ArrayAttr({static_cast<int32_t>(operands.size()),
1743  static_cast<int32_t>(normalOperands.size()),
1744  static_cast<int32_t>(unwindOperands.size()),
1745  numOpBundleOperands}));
1746  return success();
1747 }
1748 
1749 LLVMFunctionType InvokeOp::getCalleeFunctionType() {
1750  if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1751  return *varCalleeType;
1752  return getLLVMFuncType(getContext(), getResultTypes(), getArgOperands());
1753 }
1754 
1755 ///===----------------------------------------------------------------------===//
1756 /// Verifying/Printing/Parsing for LLVM::LandingpadOp.
1757 ///===----------------------------------------------------------------------===//
1758 
1759 LogicalResult LandingpadOp::verify() {
1760  Value value;
1761  if (LLVMFuncOp func = (*this)->getParentOfType<LLVMFuncOp>()) {
1762  if (!func.getPersonality())
1763  return emitError(
1764  "llvm.landingpad needs to be in a function with a personality");
1765  }
1766 
1767  // Consistency of llvm.landingpad result types is checked in
1768  // LLVMFuncOp::verify().
1769 
1770  if (!getCleanup() && getOperands().empty())
1771  return emitError("landingpad instruction expects at least one clause or "
1772  "cleanup attribute");
1773 
1774  for (unsigned idx = 0, ie = getNumOperands(); idx < ie; idx++) {
1775  value = getOperand(idx);
1776  bool isFilter = llvm::isa<LLVMArrayType>(value.getType());
1777  if (isFilter) {
1778  // FIXME: Verify filter clauses when arrays are appropriately handled
1779  } else {
1780  // catch - global addresses only.
1781  // Bitcast ops should have global addresses as their args.
1782  if (auto bcOp = value.getDefiningOp<BitcastOp>()) {
1783  if (auto addrOp = bcOp.getArg().getDefiningOp<AddressOfOp>())
1784  continue;
1785  return emitError("constant clauses expected").attachNote(bcOp.getLoc())
1786  << "global addresses expected as operand to "
1787  "bitcast used in clauses for landingpad";
1788  }
1789  // ZeroOp and AddressOfOp allowed
1790  if (value.getDefiningOp<ZeroOp>())
1791  continue;
1792  if (value.getDefiningOp<AddressOfOp>())
1793  continue;
1794  return emitError("clause #")
1795  << idx << " is not a known constant - null, addressof, bitcast";
1796  }
1797  }
1798  return success();
1799 }
1800 
1802  p << (getCleanup() ? " cleanup " : " ");
1803 
1804  // Clauses
1805  for (auto value : getOperands()) {
1806  // Similar to llvm - if clause is an array type then it is filter
1807  // clause else catch clause
1808  bool isArrayTy = llvm::isa<LLVMArrayType>(value.getType());
1809  p << '(' << (isArrayTy ? "filter " : "catch ") << value << " : "
1810  << value.getType() << ") ";
1811  }
1812 
1813  p.printOptionalAttrDict((*this)->getAttrs(), {"cleanup"});
1814 
1815  p << ": " << getType();
1816 }
1817 
1818 // <operation> ::= `llvm.landingpad` `cleanup`?
1819 // ((`catch` | `filter`) operand-type ssa-use)* attribute-dict?
1820 ParseResult LandingpadOp::parse(OpAsmParser &parser, OperationState &result) {
1821  // Check for cleanup
1822  if (succeeded(parser.parseOptionalKeyword("cleanup")))
1823  result.addAttribute("cleanup", parser.getBuilder().getUnitAttr());
1824 
1825  // Parse clauses with types
1826  while (succeeded(parser.parseOptionalLParen()) &&
1827  (succeeded(parser.parseOptionalKeyword("filter")) ||
1828  succeeded(parser.parseOptionalKeyword("catch")))) {
1830  Type ty;
1831  if (parser.parseOperand(operand) || parser.parseColon() ||
1832  parser.parseType(ty) ||
1833  parser.resolveOperand(operand, ty, result.operands) ||
1834  parser.parseRParen())
1835  return failure();
1836  }
1837 
1838  Type type;
1839  if (parser.parseColon() || parser.parseType(type))
1840  return failure();
1841 
1842  result.addTypes(type);
1843  return success();
1844 }
1845 
1846 //===----------------------------------------------------------------------===//
1847 // ExtractValueOp
1848 //===----------------------------------------------------------------------===//
1849 
1850 /// Extract the type at `position` in the LLVM IR aggregate type
1851 /// `containerType`. Each element of `position` is an index into a nested
1852 /// aggregate type. Return the resulting type or emit an error.
1854  function_ref<InFlightDiagnostic(StringRef)> emitError, Type containerType,
1855  ArrayRef<int64_t> position) {
1856  Type llvmType = containerType;
1857  if (!isCompatibleType(containerType)) {
1858  emitError("expected LLVM IR Dialect type, got ") << containerType;
1859  return {};
1860  }
1861 
1862  // Infer the element type from the structure type: iteratively step inside the
1863  // type by taking the element type, indexed by the position attribute for
1864  // structures. Check the position index before accessing, it is supposed to
1865  // be in bounds.
1866  for (int64_t idx : position) {
1867  if (auto arrayType = llvm::dyn_cast<LLVMArrayType>(llvmType)) {
1868  if (idx < 0 || static_cast<unsigned>(idx) >= arrayType.getNumElements()) {
1869  emitError("position out of bounds: ") << idx;
1870  return {};
1871  }
1872  llvmType = arrayType.getElementType();
1873  } else if (auto structType = llvm::dyn_cast<LLVMStructType>(llvmType)) {
1874  if (idx < 0 ||
1875  static_cast<unsigned>(idx) >= structType.getBody().size()) {
1876  emitError("position out of bounds: ") << idx;
1877  return {};
1878  }
1879  llvmType = structType.getBody()[idx];
1880  } else {
1881  emitError("expected LLVM IR structure/array type, got: ") << llvmType;
1882  return {};
1883  }
1884  }
1885  return llvmType;
1886 }
1887 
1888 /// Extract the type at `position` in the wrapped LLVM IR aggregate type
1889 /// `containerType`.
1891  ArrayRef<int64_t> position) {
1892  for (int64_t idx : position) {
1893  if (auto structType = llvm::dyn_cast<LLVMStructType>(llvmType))
1894  llvmType = structType.getBody()[idx];
1895  else
1896  llvmType = llvm::cast<LLVMArrayType>(llvmType).getElementType();
1897  }
1898  return llvmType;
1899 }
1900 
1901 OpFoldResult LLVM::ExtractValueOp::fold(FoldAdaptor adaptor) {
1902  if (auto extractValueOp = getContainer().getDefiningOp<ExtractValueOp>()) {
1903  SmallVector<int64_t, 4> newPos(extractValueOp.getPosition());
1904  newPos.append(getPosition().begin(), getPosition().end());
1905  setPosition(newPos);
1906  getContainerMutable().set(extractValueOp.getContainer());
1907  return getResult();
1908  }
1909 
1910  {
1911  DenseElementsAttr constval;
1912  matchPattern(getContainer(), m_Constant(&constval));
1913  if (constval && constval.getElementType() == getType()) {
1914  if (isa<SplatElementsAttr>(constval))
1915  return constval.getSplatValue<Attribute>();
1916  if (getPosition().size() == 1)
1917  return constval.getValues<Attribute>()[getPosition()[0]];
1918  }
1919  }
1920 
1921  auto insertValueOp = getContainer().getDefiningOp<InsertValueOp>();
1922  OpFoldResult result = {};
1923  ArrayRef<int64_t> extractPos = getPosition();
1924  bool switchedToInsertedValue = false;
1925  while (insertValueOp) {
1926  ArrayRef<int64_t> insertPos = insertValueOp.getPosition();
1927  auto extractPosSize = extractPos.size();
1928  auto insertPosSize = insertPos.size();
1929 
1930  // Case 1: Exact match of positions.
1931  if (extractPos == insertPos)
1932  return insertValueOp.getValue();
1933 
1934  // Case 2: Insert position is a prefix of extract position. Continue
1935  // traversal with the inserted value. Example:
1936  // ```
1937  // %0 = llvm.insertvalue %arg1, %undef[0] : !llvm.struct<(i32, i32, i32)>
1938  // %1 = llvm.insertvalue %arg2, %0[1] : !llvm.struct<(i32, i32, i32)>
1939  // %2 = llvm.insertvalue %arg3, %1[2] : !llvm.struct<(i32, i32, i32)>
1940  // %3 = llvm.insertvalue %2, %foo[0]
1941  // : !llvm.struct<(struct<(i32, i32, i32)>, i64)>
1942  // %4 = llvm.extractvalue %3[0, 0]
1943  // : !llvm.struct<(struct<(i32, i32, i32)>, i64)>
1944  // ```
1945  // In the above example, %4 is folded to %arg1.
1946  if (extractPosSize > insertPosSize &&
1947  extractPos.take_front(insertPosSize) == insertPos) {
1948  insertValueOp = insertValueOp.getValue().getDefiningOp<InsertValueOp>();
1949  extractPos = extractPos.drop_front(insertPosSize);
1950  switchedToInsertedValue = true;
1951  continue;
1952  }
1953 
1954  // Case 3: Try to continue the traversal with the container value.
1955  unsigned min = std::min(extractPosSize, insertPosSize);
1956 
1957  // If one is fully prefix of the other, stop propagating back as it will
1958  // miss dependencies. For instance, %3 should not fold to %f0 in the
1959  // following example:
1960  // ```
1961  // %1 = llvm.insertvalue %f0, %0[0, 0] :
1962  // !llvm.array<4 x !llvm.array<4 x f32>>
1963  // %2 = llvm.insertvalue %arr, %1[0] :
1964  // !llvm.array<4 x !llvm.array<4 x f32>>
1965  // %3 = llvm.extractvalue %2[0, 0] : !llvm.array<4 x !llvm.array<4 x f32>>
1966  // ```
1967  if (extractPos.take_front(min) == insertPos.take_front(min))
1968  return result;
1969  // If neither a prefix, nor the exact position, we can extract out of the
1970  // value being inserted into. Moreover, we can try again if that operand
1971  // is itself an insertvalue expression.
1972  if (!switchedToInsertedValue) {
1973  // Do not swap out the container operand if we decided earlier to
1974  // continue the traversal with the inserted value (Case 2).
1975  getContainerMutable().assign(insertValueOp.getContainer());
1976  result = getResult();
1977  }
1978  insertValueOp = insertValueOp.getContainer().getDefiningOp<InsertValueOp>();
1979  }
1980  return result;
1981 }
1982 
1983 LogicalResult ExtractValueOp::verify() {
1984  auto emitError = [this](StringRef msg) { return emitOpError(msg); };
1986  emitError, getContainer().getType(), getPosition());
1987  if (!valueType)
1988  return failure();
1989 
1990  if (getRes().getType() != valueType)
1991  return emitOpError() << "Type mismatch: extracting from "
1992  << getContainer().getType() << " should produce "
1993  << valueType << " but this op returns "
1994  << getRes().getType();
1995  return success();
1996 }
1997 
1998 void ExtractValueOp::build(OpBuilder &builder, OperationState &state,
1999  Value container, ArrayRef<int64_t> position) {
2000  build(builder, state,
2001  getInsertExtractValueElementType(container.getType(), position),
2002  container, builder.getAttr<DenseI64ArrayAttr>(position));
2003 }
2004 
2005 //===----------------------------------------------------------------------===//
2006 // InsertValueOp
2007 //===----------------------------------------------------------------------===//
2008 
2009 /// Infer the value type from the container type and position.
2010 static ParseResult
2012  Type containerType,
2013  DenseI64ArrayAttr position) {
2015  [&](StringRef msg) {
2016  return parser.emitError(parser.getCurrentLocation(), msg);
2017  },
2018  containerType, position.asArrayRef());
2019  return success(!!valueType);
2020 }
2021 
2022 /// Nothing to print for an inferred type.
2024  Operation *op, Type valueType,
2025  Type containerType,
2026  DenseI64ArrayAttr position) {}
2027 
2028 LogicalResult InsertValueOp::verify() {
2029  auto emitError = [this](StringRef msg) { return emitOpError(msg); };
2031  emitError, getContainer().getType(), getPosition());
2032  if (!valueType)
2033  return failure();
2034 
2035  if (getValue().getType() != valueType)
2036  return emitOpError() << "Type mismatch: cannot insert "
2037  << getValue().getType() << " into "
2038  << getContainer().getType();
2039 
2040  return success();
2041 }
2042 
2043 //===----------------------------------------------------------------------===//
2044 // ReturnOp
2045 //===----------------------------------------------------------------------===//
2046 
2047 LogicalResult ReturnOp::verify() {
2048  auto parent = (*this)->getParentOfType<LLVMFuncOp>();
2049  if (!parent)
2050  return success();
2051 
2052  Type expectedType = parent.getFunctionType().getReturnType();
2053  if (llvm::isa<LLVMVoidType>(expectedType)) {
2054  if (!getArg())
2055  return success();
2056  InFlightDiagnostic diag = emitOpError("expected no operands");
2057  diag.attachNote(parent->getLoc()) << "when returning from function";
2058  return diag;
2059  }
2060  if (!getArg()) {
2061  if (llvm::isa<LLVMVoidType>(expectedType))
2062  return success();
2063  InFlightDiagnostic diag = emitOpError("expected 1 operand");
2064  diag.attachNote(parent->getLoc()) << "when returning from function";
2065  return diag;
2066  }
2067  if (expectedType != getArg().getType()) {
2068  InFlightDiagnostic diag = emitOpError("mismatching result types");
2069  diag.attachNote(parent->getLoc()) << "when returning from function";
2070  return diag;
2071  }
2072  return success();
2073 }
2074 
2075 //===----------------------------------------------------------------------===//
2076 // LLVM::AddressOfOp.
2077 //===----------------------------------------------------------------------===//
2078 
2079 GlobalOp AddressOfOp::getGlobal(SymbolTableCollection &symbolTable) {
2080  return dyn_cast_or_null<GlobalOp>(
2081  symbolTable.lookupSymbolIn(parentLLVMModule(*this), getGlobalNameAttr()));
2082 }
2083 
2084 LLVMFuncOp AddressOfOp::getFunction(SymbolTableCollection &symbolTable) {
2085  return dyn_cast_or_null<LLVMFuncOp>(
2086  symbolTable.lookupSymbolIn(parentLLVMModule(*this), getGlobalNameAttr()));
2087 }
2088 
2089 AliasOp AddressOfOp::getAlias(SymbolTableCollection &symbolTable) {
2090  return dyn_cast_or_null<AliasOp>(
2091  symbolTable.lookupSymbolIn(parentLLVMModule(*this), getGlobalNameAttr()));
2092 }
2093 
2094 IFuncOp AddressOfOp::getIFunc(SymbolTableCollection &symbolTable) {
2095  return dyn_cast_or_null<IFuncOp>(
2096  symbolTable.lookupSymbolIn(parentLLVMModule(*this), getGlobalNameAttr()));
2097 }
2098 
2099 LogicalResult
2100 AddressOfOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
2101  Operation *symbol =
2102  symbolTable.lookupSymbolIn(parentLLVMModule(*this), getGlobalNameAttr());
2103 
2104  auto global = dyn_cast_or_null<GlobalOp>(symbol);
2105  auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2106  auto alias = dyn_cast_or_null<AliasOp>(symbol);
2107  auto ifunc = dyn_cast_or_null<IFuncOp>(symbol);
2108 
2109  if (!global && !function && !alias && !ifunc)
2110  return emitOpError("must reference a global defined by 'llvm.mlir.global', "
2111  "'llvm.mlir.alias' or 'llvm.func' or 'llvm.mlir.ifunc'");
2112 
2113  LLVMPointerType type = getType();
2114  if ((global && global.getAddrSpace() != type.getAddressSpace()) ||
2115  (alias && alias.getAddrSpace() != type.getAddressSpace()))
2116  return emitOpError("pointer address space must match address space of the "
2117  "referenced global or alias");
2118 
2119  return success();
2120 }
2121 
2122 // AddressOfOp constant-folds to the global symbol name.
2123 OpFoldResult LLVM::AddressOfOp::fold(FoldAdaptor) {
2124  return getGlobalNameAttr();
2125 }
2126 
2127 //===----------------------------------------------------------------------===//
2128 // LLVM::DSOLocalEquivalentOp
2129 //===----------------------------------------------------------------------===//
2130 
2131 LLVMFuncOp
2132 DSOLocalEquivalentOp::getFunction(SymbolTableCollection &symbolTable) {
2133  return dyn_cast_or_null<LLVMFuncOp>(symbolTable.lookupSymbolIn(
2134  parentLLVMModule(*this), getFunctionNameAttr()));
2135 }
2136 
2137 AliasOp DSOLocalEquivalentOp::getAlias(SymbolTableCollection &symbolTable) {
2138  return dyn_cast_or_null<AliasOp>(symbolTable.lookupSymbolIn(
2139  parentLLVMModule(*this), getFunctionNameAttr()));
2140 }
2141 
2142 LogicalResult
2143 DSOLocalEquivalentOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
2144  Operation *symbol = symbolTable.lookupSymbolIn(parentLLVMModule(*this),
2145  getFunctionNameAttr());
2146  auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2147  auto alias = dyn_cast_or_null<AliasOp>(symbol);
2148 
2149  if (!function && !alias)
2150  return emitOpError(
2151  "must reference a global defined by 'llvm.func' or 'llvm.mlir.alias'");
2152 
2153  if (alias) {
2154  if (alias.getInitializer()
2155  .walk([&](AddressOfOp addrOp) {
2156  if (addrOp.getGlobal(symbolTable))
2157  return WalkResult::interrupt();
2158  return WalkResult::advance();
2159  })
2160  .wasInterrupted())
2161  return emitOpError("must reference an alias to a function");
2162  }
2163 
2164  if ((function && function.getLinkage() == LLVM::Linkage::ExternWeak) ||
2165  (alias && alias.getLinkage() == LLVM::Linkage::ExternWeak))
2166  return emitOpError(
2167  "target function with 'extern_weak' linkage not allowed");
2168 
2169  return success();
2170 }
2171 
2172 /// Fold a dso_local_equivalent operation to a dedicated dso_local_equivalent
2173 /// attribute.
2174 OpFoldResult DSOLocalEquivalentOp::fold(FoldAdaptor) {
2175  return DSOLocalEquivalentAttr::get(getContext(), getFunctionNameAttr());
2176 }
2177 
2178 //===----------------------------------------------------------------------===//
2179 // Verifier for LLVM::ComdatOp.
2180 //===----------------------------------------------------------------------===//
2181 
2182 void ComdatOp::build(OpBuilder &builder, OperationState &result,
2183  StringRef symName) {
2184  result.addAttribute(getSymNameAttrName(result.name),
2185  builder.getStringAttr(symName));
2186  Region *body = result.addRegion();
2187  body->emplaceBlock();
2188 }
2189 
2190 LogicalResult ComdatOp::verifyRegions() {
2191  Region &body = getBody();
2192  for (Operation &op : body.getOps())
2193  if (!isa<ComdatSelectorOp>(op))
2194  return op.emitError(
2195  "only comdat selector symbols can appear in a comdat region");
2196 
2197  return success();
2198 }
2199 
2200 //===----------------------------------------------------------------------===//
2201 // Builder, printer and verifier for LLVM::GlobalOp.
2202 //===----------------------------------------------------------------------===//
2203 
2204 void GlobalOp::build(OpBuilder &builder, OperationState &result, Type type,
2205  bool isConstant, Linkage linkage, StringRef name,
2206  Attribute value, uint64_t alignment, unsigned addrSpace,
2207  bool dsoLocal, bool threadLocal, SymbolRefAttr comdat,
2209  ArrayRef<Attribute> dbgExprs) {
2210  result.addAttribute(getSymNameAttrName(result.name),
2211  builder.getStringAttr(name));
2212  result.addAttribute(getGlobalTypeAttrName(result.name), TypeAttr::get(type));
2213  if (isConstant)
2214  result.addAttribute(getConstantAttrName(result.name),
2215  builder.getUnitAttr());
2216  if (value)
2217  result.addAttribute(getValueAttrName(result.name), value);
2218  if (dsoLocal)
2219  result.addAttribute(getDsoLocalAttrName(result.name),
2220  builder.getUnitAttr());
2221  if (threadLocal)
2222  result.addAttribute(getThreadLocal_AttrName(result.name),
2223  builder.getUnitAttr());
2224  if (comdat)
2225  result.addAttribute(getComdatAttrName(result.name), comdat);
2226 
2227  // Only add an alignment attribute if the "alignment" input
2228  // is different from 0. The value must also be a power of two, but
2229  // this is tested in GlobalOp::verify, not here.
2230  if (alignment != 0)
2231  result.addAttribute(getAlignmentAttrName(result.name),
2232  builder.getI64IntegerAttr(alignment));
2233 
2234  result.addAttribute(getLinkageAttrName(result.name),
2235  LinkageAttr::get(builder.getContext(), linkage));
2236  if (addrSpace != 0)
2237  result.addAttribute(getAddrSpaceAttrName(result.name),
2238  builder.getI32IntegerAttr(addrSpace));
2239  result.attributes.append(attrs.begin(), attrs.end());
2240 
2241  if (!dbgExprs.empty())
2242  result.addAttribute(getDbgExprsAttrName(result.name),
2243  ArrayAttr::get(builder.getContext(), dbgExprs));
2244 
2245  result.addRegion();
2246 }
2247 
2248 template <typename OpType>
2249 static void printCommonGlobalAndAlias(OpAsmPrinter &p, OpType op) {
2250  p << ' ' << stringifyLinkage(op.getLinkage()) << ' ';
2251  StringRef visibility = stringifyVisibility(op.getVisibility_());
2252  if (!visibility.empty())
2253  p << visibility << ' ';
2254  if (op.getThreadLocal_())
2255  p << "thread_local ";
2256  if (auto unnamedAddr = op.getUnnamedAddr()) {
2257  StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2258  if (!str.empty())
2259  p << str << ' ';
2260  }
2261 }
2262 
2263 void GlobalOp::print(OpAsmPrinter &p) {
2264  printCommonGlobalAndAlias<GlobalOp>(p, *this);
2265  if (getConstant())
2266  p << "constant ";
2267  p.printSymbolName(getSymName());
2268  p << '(';
2269  if (auto value = getValueOrNull())
2270  p.printAttribute(value);
2271  p << ')';
2272  if (auto comdat = getComdat())
2273  p << " comdat(" << *comdat << ')';
2274 
2275  // Note that the alignment attribute is printed using the
2276  // default syntax here, even though it is an inherent attribute
2277  // (as defined in https://mlir.llvm.org/docs/LangRef/#attributes)
2278  p.printOptionalAttrDict((*this)->getAttrs(),
2279  {SymbolTable::getSymbolAttrName(),
2280  getGlobalTypeAttrName(), getConstantAttrName(),
2281  getValueAttrName(), getLinkageAttrName(),
2282  getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
2283  getVisibility_AttrName(), getComdatAttrName()});
2284 
2285  // Print the trailing type unless it's a string global.
2286  if (llvm::dyn_cast_or_null<StringAttr>(getValueOrNull()))
2287  return;
2288  p << " : " << getType();
2289 
2290  Region &initializer = getInitializerRegion();
2291  if (!initializer.empty()) {
2292  p << ' ';
2293  p.printRegion(initializer, /*printEntryBlockArgs=*/false);
2294  }
2295 }
2296 
2297 static LogicalResult verifyComdat(Operation *op,
2298  std::optional<SymbolRefAttr> attr) {
2299  if (!attr)
2300  return success();
2301 
2302  auto *comdatSelector = SymbolTable::lookupNearestSymbolFrom(op, *attr);
2303  if (!isa_and_nonnull<ComdatSelectorOp>(comdatSelector))
2304  return op->emitError() << "expected comdat symbol";
2305 
2306  return success();
2307 }
2308 
2309 static LogicalResult verifyBlockTags(LLVMFuncOp funcOp) {
2310  llvm::DenseSet<BlockTagAttr> blockTags;
2311  // Note that presence of `BlockTagOp`s currently can't prevent an unrecheable
2312  // block to be removed by canonicalizer's region simplify pass, which needs to
2313  // be dialect aware to allow extra constraints to be described.
2314  WalkResult res = funcOp.walk([&](BlockTagOp blockTagOp) {
2315  if (blockTags.contains(blockTagOp.getTag())) {
2316  blockTagOp.emitError()
2317  << "duplicate block tag '" << blockTagOp.getTag().getId()
2318  << "' in the same function: ";
2319  return WalkResult::interrupt();
2320  }
2321  blockTags.insert(blockTagOp.getTag());
2322  return WalkResult::advance();
2323  });
2324 
2325  return failure(res.wasInterrupted());
2326 }
2327 
2328 /// Parse common attributes that might show up in the same order in both
2329 /// GlobalOp and AliasOp.
2330 template <typename OpType>
2331 static ParseResult parseCommonGlobalAndAlias(OpAsmParser &parser,
2332  OperationState &result) {
2333  MLIRContext *ctx = parser.getContext();
2334  // Parse optional linkage, default to External.
2335  result.addAttribute(
2336  OpType::getLinkageAttrName(result.name),
2337  LLVM::LinkageAttr::get(ctx, parseOptionalLLVMKeyword<Linkage>(
2338  parser, LLVM::Linkage::External)));
2339 
2340  // Parse optional visibility, default to Default.
2341  result.addAttribute(OpType::getVisibility_AttrName(result.name),
2342  parser.getBuilder().getI64IntegerAttr(
2343  parseOptionalLLVMKeyword<LLVM::Visibility, int64_t>(
2344  parser, LLVM::Visibility::Default)));
2345 
2346  if (succeeded(parser.parseOptionalKeyword("thread_local")))
2347  result.addAttribute(OpType::getThreadLocal_AttrName(result.name),
2348  parser.getBuilder().getUnitAttr());
2349 
2350  // Parse optional UnnamedAddr, default to None.
2351  result.addAttribute(OpType::getUnnamedAddrAttrName(result.name),
2352  parser.getBuilder().getI64IntegerAttr(
2353  parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
2354  parser, LLVM::UnnamedAddr::None)));
2355 
2356  return success();
2357 }
2358 
2359 // operation ::= `llvm.mlir.global` linkage? visibility?
2360 // (`unnamed_addr` | `local_unnamed_addr`)?
2361 // `thread_local`? `constant`? `@` identifier
2362 // `(` attribute? `)` (`comdat(` symbol-ref-id `)`)?
2363 // attribute-list? (`:` type)? region?
2364 //
2365 // The type can be omitted for string attributes, in which case it will be
2366 // inferred from the value of the string as [strlen(value) x i8].
2367 ParseResult GlobalOp::parse(OpAsmParser &parser, OperationState &result) {
2368  // Call into common parsing between GlobalOp and AliasOp.
2369  if (parseCommonGlobalAndAlias<GlobalOp>(parser, result).failed())
2370  return failure();
2371 
2372  if (succeeded(parser.parseOptionalKeyword("constant")))
2373  result.addAttribute(getConstantAttrName(result.name),
2374  parser.getBuilder().getUnitAttr());
2375 
2376  StringAttr name;
2377  if (parser.parseSymbolName(name, getSymNameAttrName(result.name),
2378  result.attributes) ||
2379  parser.parseLParen())
2380  return failure();
2381 
2382  Attribute value;
2383  if (parser.parseOptionalRParen()) {
2384  if (parser.parseAttribute(value, getValueAttrName(result.name),
2385  result.attributes) ||
2386  parser.parseRParen())
2387  return failure();
2388  }
2389 
2390  if (succeeded(parser.parseOptionalKeyword("comdat"))) {
2391  SymbolRefAttr comdat;
2392  if (parser.parseLParen() || parser.parseAttribute(comdat) ||
2393  parser.parseRParen())
2394  return failure();
2395 
2396  result.addAttribute(getComdatAttrName(result.name), comdat);
2397  }
2398 
2399  SmallVector<Type, 1> types;
2400  if (parser.parseOptionalAttrDict(result.attributes) ||
2401  parser.parseOptionalColonTypeList(types))
2402  return failure();
2403 
2404  if (types.size() > 1)
2405  return parser.emitError(parser.getNameLoc(), "expected zero or one type");
2406 
2407  Region &initRegion = *result.addRegion();
2408  if (types.empty()) {
2409  if (auto strAttr = llvm::dyn_cast_or_null<StringAttr>(value)) {
2410  MLIRContext *context = parser.getContext();
2411  auto arrayType = LLVM::LLVMArrayType::get(IntegerType::get(context, 8),
2412  strAttr.getValue().size());
2413  types.push_back(arrayType);
2414  } else {
2415  return parser.emitError(parser.getNameLoc(),
2416  "type can only be omitted for string globals");
2417  }
2418  } else {
2419  OptionalParseResult parseResult =
2420  parser.parseOptionalRegion(initRegion, /*arguments=*/{},
2421  /*argTypes=*/{});
2422  if (parseResult.has_value() && failed(*parseResult))
2423  return failure();
2424  }
2425 
2426  result.addAttribute(getGlobalTypeAttrName(result.name),
2427  TypeAttr::get(types[0]));
2428  return success();
2429 }
2430 
2431 static bool isZeroAttribute(Attribute value) {
2432  if (auto intValue = llvm::dyn_cast<IntegerAttr>(value))
2433  return intValue.getValue().isZero();
2434  if (auto fpValue = llvm::dyn_cast<FloatAttr>(value))
2435  return fpValue.getValue().isZero();
2436  if (auto splatValue = llvm::dyn_cast<SplatElementsAttr>(value))
2437  return isZeroAttribute(splatValue.getSplatValue<Attribute>());
2438  if (auto elementsValue = llvm::dyn_cast<ElementsAttr>(value))
2439  return llvm::all_of(elementsValue.getValues<Attribute>(), isZeroAttribute);
2440  if (auto arrayValue = llvm::dyn_cast<ArrayAttr>(value))
2441  return llvm::all_of(arrayValue.getValue(), isZeroAttribute);
2442  return false;
2443 }
2444 
2445 LogicalResult GlobalOp::verify() {
2446  bool validType = isCompatibleOuterType(getType())
2447  ? !llvm::isa<LLVMVoidType, LLVMTokenType,
2448  LLVMMetadataType, LLVMLabelType>(getType())
2449  : llvm::isa<PointerElementTypeInterface>(getType());
2450  if (!validType)
2451  return emitOpError(
2452  "expects type to be a valid element type for an LLVM global");
2453  if ((*this)->getParentOp() && !satisfiesLLVMModule((*this)->getParentOp()))
2454  return emitOpError("must appear at the module level");
2455 
2456  if (auto strAttr = llvm::dyn_cast_or_null<StringAttr>(getValueOrNull())) {
2457  auto type = llvm::dyn_cast<LLVMArrayType>(getType());
2458  IntegerType elementType =
2459  type ? llvm::dyn_cast<IntegerType>(type.getElementType()) : nullptr;
2460  if (!elementType || elementType.getWidth() != 8 ||
2461  type.getNumElements() != strAttr.getValue().size())
2462  return emitOpError(
2463  "requires an i8 array type of the length equal to that of the string "
2464  "attribute");
2465  }
2466 
2467  if (auto targetExtType = dyn_cast<LLVMTargetExtType>(getType())) {
2468  if (!targetExtType.hasProperty(LLVMTargetExtType::CanBeGlobal))
2469  return emitOpError()
2470  << "this target extension type cannot be used in a global";
2471 
2472  if (Attribute value = getValueOrNull())
2473  return emitOpError() << "global with target extension type can only be "
2474  "initialized with zero-initializer";
2475  }
2476 
2477  if (getLinkage() == Linkage::Common) {
2478  if (Attribute value = getValueOrNull()) {
2479  if (!isZeroAttribute(value)) {
2480  return emitOpError()
2481  << "expected zero value for '"
2482  << stringifyLinkage(Linkage::Common) << "' linkage";
2483  }
2484  }
2485  }
2486 
2487  if (getLinkage() == Linkage::Appending) {
2488  if (!llvm::isa<LLVMArrayType>(getType())) {
2489  return emitOpError() << "expected array type for '"
2490  << stringifyLinkage(Linkage::Appending)
2491  << "' linkage";
2492  }
2493  }
2494 
2495  if (failed(verifyComdat(*this, getComdat())))
2496  return failure();
2497 
2498  std::optional<uint64_t> alignAttr = getAlignment();
2499  if (alignAttr.has_value()) {
2500  uint64_t value = alignAttr.value();
2501  if (!llvm::isPowerOf2_64(value))
2502  return emitError() << "alignment attribute is not a power of 2";
2503  }
2504 
2505  return success();
2506 }
2507 
2508 LogicalResult GlobalOp::verifyRegions() {
2509  if (Block *b = getInitializerBlock()) {
2510  ReturnOp ret = cast<ReturnOp>(b->getTerminator());
2511  if (ret.operand_type_begin() == ret.operand_type_end())
2512  return emitOpError("initializer region cannot return void");
2513  if (*ret.operand_type_begin() != getType())
2514  return emitOpError("initializer region type ")
2515  << *ret.operand_type_begin() << " does not match global type "
2516  << getType();
2517 
2518  for (Operation &op : *b) {
2519  auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2520  if (!iface || !iface.hasNoEffect())
2521  return op.emitError()
2522  << "ops with side effects not allowed in global initializers";
2523  }
2524 
2525  if (getValueOrNull())
2526  return emitOpError("cannot have both initializer value and region");
2527  }
2528 
2529  return success();
2530 }
2531 
2532 //===----------------------------------------------------------------------===//
2533 // LLVM::GlobalCtorsOp
2534 //===----------------------------------------------------------------------===//
2535 
2536 static LogicalResult checkGlobalXtorData(Operation *op, ArrayAttr data) {
2537  if (data.empty())
2538  return success();
2539 
2540  if (llvm::all_of(data.getAsRange<Attribute>(), [](Attribute v) {
2541  return isa<FlatSymbolRefAttr, ZeroAttr>(v);
2542  }))
2543  return success();
2544  return op->emitError("data element must be symbol or #llvm.zero");
2545 }
2546 
2547 LogicalResult
2548 GlobalCtorsOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
2549  for (Attribute ctor : getCtors()) {
2550  if (failed(verifySymbolAttrUse(llvm::cast<FlatSymbolRefAttr>(ctor), *this,
2551  symbolTable)))
2552  return failure();
2553  }
2554  return success();
2555 }
2556 
2557 LogicalResult GlobalCtorsOp::verify() {
2558  if (checkGlobalXtorData(*this, getData()).failed())
2559  return failure();
2560 
2561  if (getCtors().size() == getPriorities().size() &&
2562  getCtors().size() == getData().size())
2563  return success();
2564  return emitError(
2565  "ctors, priorities, and data must have the same number of elements");
2566 }
2567 
2568 //===----------------------------------------------------------------------===//
2569 // LLVM::GlobalDtorsOp
2570 //===----------------------------------------------------------------------===//
2571 
2572 LogicalResult
2573 GlobalDtorsOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
2574  for (Attribute dtor : getDtors()) {
2575  if (failed(verifySymbolAttrUse(llvm::cast<FlatSymbolRefAttr>(dtor), *this,
2576  symbolTable)))
2577  return failure();
2578  }
2579  return success();
2580 }
2581 
2582 LogicalResult GlobalDtorsOp::verify() {
2583  if (checkGlobalXtorData(*this, getData()).failed())
2584  return failure();
2585 
2586  if (getDtors().size() == getPriorities().size() &&
2587  getDtors().size() == getData().size())
2588  return success();
2589  return emitError(
2590  "dtors, priorities, and data must have the same number of elements");
2591 }
2592 
2593 //===----------------------------------------------------------------------===//
2594 // Builder, printer and verifier for LLVM::AliasOp.
2595 //===----------------------------------------------------------------------===//
2596 
2597 void AliasOp::build(OpBuilder &builder, OperationState &result, Type type,
2598  Linkage linkage, StringRef name, bool dsoLocal,
2599  bool threadLocal, ArrayRef<NamedAttribute> attrs) {
2600  result.addAttribute(getSymNameAttrName(result.name),
2601  builder.getStringAttr(name));
2602  result.addAttribute(getAliasTypeAttrName(result.name), TypeAttr::get(type));
2603  if (dsoLocal)
2604  result.addAttribute(getDsoLocalAttrName(result.name),
2605  builder.getUnitAttr());
2606  if (threadLocal)
2607  result.addAttribute(getThreadLocal_AttrName(result.name),
2608  builder.getUnitAttr());
2609 
2610  result.addAttribute(getLinkageAttrName(result.name),
2611  LinkageAttr::get(builder.getContext(), linkage));
2612  result.attributes.append(attrs.begin(), attrs.end());
2613 
2614  result.addRegion();
2615 }
2616 
2617 void AliasOp::print(OpAsmPrinter &p) {
2618  printCommonGlobalAndAlias<AliasOp>(p, *this);
2619 
2620  p.printSymbolName(getSymName());
2621  p.printOptionalAttrDict((*this)->getAttrs(),
2622  {SymbolTable::getSymbolAttrName(),
2623  getAliasTypeAttrName(), getLinkageAttrName(),
2624  getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
2625  getVisibility_AttrName()});
2626 
2627  // Print the trailing type.
2628  p << " : " << getType() << ' ';
2629  // Print the initializer region.
2630  p.printRegion(getInitializerRegion(), /*printEntryBlockArgs=*/false);
2631 }
2632 
2633 // operation ::= `llvm.mlir.alias` linkage? visibility?
2634 // (`unnamed_addr` | `local_unnamed_addr`)?
2635 // `thread_local`? `@` identifier
2636 // `(` attribute? `)`
2637 // attribute-list? `:` type region
2638 //
2639 ParseResult AliasOp::parse(OpAsmParser &parser, OperationState &result) {
2640  // Call into common parsing between GlobalOp and AliasOp.
2641  if (parseCommonGlobalAndAlias<AliasOp>(parser, result).failed())
2642  return failure();
2643 
2644  StringAttr name;
2645  if (parser.parseSymbolName(name, getSymNameAttrName(result.name),
2646  result.attributes))
2647  return failure();
2648 
2649  SmallVector<Type, 1> types;
2650  if (parser.parseOptionalAttrDict(result.attributes) ||
2651  parser.parseOptionalColonTypeList(types))
2652  return failure();
2653 
2654  if (types.size() > 1)
2655  return parser.emitError(parser.getNameLoc(), "expected zero or one type");
2656 
2657  Region &initRegion = *result.addRegion();
2658  if (parser.parseRegion(initRegion).failed())
2659  return failure();
2660 
2661  result.addAttribute(getAliasTypeAttrName(result.name),
2662  TypeAttr::get(types[0]));
2663  return success();
2664 }
2665 
2666 LogicalResult AliasOp::verify() {
2667  bool validType = isCompatibleOuterType(getType())
2668  ? !llvm::isa<LLVMVoidType, LLVMTokenType,
2669  LLVMMetadataType, LLVMLabelType>(getType())
2670  : llvm::isa<PointerElementTypeInterface>(getType());
2671  if (!validType)
2672  return emitOpError(
2673  "expects type to be a valid element type for an LLVM global alias");
2674 
2675  // This matches LLVM IR verification logic, see llvm/lib/IR/Verifier.cpp
2676  switch (getLinkage()) {
2677  case Linkage::External:
2678  case Linkage::Internal:
2679  case Linkage::Private:
2680  case Linkage::Weak:
2681  case Linkage::WeakODR:
2682  case Linkage::Linkonce:
2683  case Linkage::LinkonceODR:
2684  case Linkage::AvailableExternally:
2685  break;
2686  default:
2687  return emitOpError()
2688  << "'" << stringifyLinkage(getLinkage())
2689  << "' linkage not supported in aliases, available options: private, "
2690  "internal, linkonce, weak, linkonce_odr, weak_odr, external or "
2691  "available_externally";
2692  }
2693 
2694  return success();
2695 }
2696 
2697 LogicalResult AliasOp::verifyRegions() {
2698  Block &b = getInitializerBlock();
2699  auto ret = cast<ReturnOp>(b.getTerminator());
2700  if (ret.getNumOperands() == 0 ||
2701  !isa<LLVM::LLVMPointerType>(ret.getOperand(0).getType()))
2702  return emitOpError("initializer region must always return a pointer");
2703 
2704  for (Operation &op : b) {
2705  auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2706  if (!iface || !iface.hasNoEffect())
2707  return op.emitError()
2708  << "ops with side effects are not allowed in alias initializers";
2709  }
2710 
2711  return success();
2712 }
2713 
2714 unsigned AliasOp::getAddrSpace() {
2715  Block &initializer = getInitializerBlock();
2716  auto ret = cast<ReturnOp>(initializer.getTerminator());
2717  auto ptrTy = cast<LLVMPointerType>(ret.getOperand(0).getType());
2718  return ptrTy.getAddressSpace();
2719 }
2720 
2721 //===----------------------------------------------------------------------===//
2722 // IFuncOp
2723 //===----------------------------------------------------------------------===//
2724 
2725 void IFuncOp::build(OpBuilder &builder, OperationState &result, StringRef name,
2726  Type iFuncType, StringRef resolverName, Type resolverType,
2727  Linkage linkage, LLVM::Visibility visibility) {
2728  return build(builder, result, name, iFuncType, resolverName, resolverType,
2729  linkage, /*dso_local=*/false, /*address_space=*/0,
2730  UnnamedAddr::None, visibility);
2731 }
2732 
2733 LogicalResult IFuncOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
2734  Operation *symbol =
2735  symbolTable.lookupSymbolIn(parentLLVMModule(*this), getResolverAttr());
2736  // This matches LLVM IR verification logic, see llvm/lib/IR/Verifier.cpp
2737  auto resolver = dyn_cast<LLVMFuncOp>(symbol);
2738  auto alias = dyn_cast<AliasOp>(symbol);
2739  while (alias) {
2740  Block &initBlock = alias.getInitializerBlock();
2741  auto returnOp = cast<ReturnOp>(initBlock.getTerminator());
2742  auto addrOp = returnOp.getArg().getDefiningOp<AddressOfOp>();
2743  // FIXME: This is a best effort solution. The AliasOp body might be more
2744  // complex and in that case we bail out with success. To completely match
2745  // the LLVM IR logic it would be necessary to implement proper alias and
2746  // cast stripping.
2747  if (!addrOp)
2748  return success();
2749  resolver = addrOp.getFunction(symbolTable);
2750  alias = addrOp.getAlias(symbolTable);
2751  }
2752  if (!resolver)
2753  return emitOpError("must have a function resolver");
2754  Linkage linkage = resolver.getLinkage();
2755  if (resolver.isExternal() || linkage == Linkage::AvailableExternally)
2756  return emitOpError("resolver must be a definition");
2757  if (!isa<LLVMPointerType>(resolver.getFunctionType().getReturnType()))
2758  return emitOpError("resolver must return a pointer");
2759  auto resolverPtr = dyn_cast<LLVMPointerType>(getResolverType());
2760  if (!resolverPtr || resolverPtr.getAddressSpace() != getAddressSpace())
2761  return emitOpError("resolver has incorrect type");
2762  return success();
2763 }
2764 
2765 LogicalResult IFuncOp::verify() {
2766  switch (getLinkage()) {
2767  case Linkage::External:
2768  case Linkage::Internal:
2769  case Linkage::Private:
2770  case Linkage::Weak:
2771  case Linkage::WeakODR:
2772  case Linkage::Linkonce:
2773  case Linkage::LinkonceODR:
2774  break;
2775  default:
2776  return emitOpError() << "'" << stringifyLinkage(getLinkage())
2777  << "' linkage not supported in ifuncs, available "
2778  "options: private, internal, linkonce, weak, "
2779  "linkonce_odr, weak_odr, or external linkage";
2780  }
2781  return success();
2782 }
2783 
2784 //===----------------------------------------------------------------------===//
2785 // ShuffleVectorOp
2786 //===----------------------------------------------------------------------===//
2787 
2788 void ShuffleVectorOp::build(OpBuilder &builder, OperationState &state, Value v1,
2789  Value v2, DenseI32ArrayAttr mask,
2790  ArrayRef<NamedAttribute> attrs) {
2791  auto containerType = v1.getType();
2792  auto vType = LLVM::getVectorType(
2793  cast<VectorType>(containerType).getElementType(), mask.size(),
2794  LLVM::isScalableVectorType(containerType));
2795  build(builder, state, vType, v1, v2, mask);
2796  state.addAttributes(attrs);
2797 }
2798 
2799 void ShuffleVectorOp::build(OpBuilder &builder, OperationState &state, Value v1,
2800  Value v2, ArrayRef<int32_t> mask) {
2801  build(builder, state, v1, v2, builder.getDenseI32ArrayAttr(mask));
2802 }
2803 
2804 /// Build the result type of a shuffle vector operation.
2805 static ParseResult parseShuffleType(AsmParser &parser, Type v1Type,
2806  Type &resType, DenseI32ArrayAttr mask) {
2807  if (!LLVM::isCompatibleVectorType(v1Type))
2808  return parser.emitError(parser.getCurrentLocation(),
2809  "expected an LLVM compatible vector type");
2810  resType =
2811  LLVM::getVectorType(cast<VectorType>(v1Type).getElementType(),
2812  mask.size(), LLVM::isScalableVectorType(v1Type));
2813  return success();
2814 }
2815 
2816 /// Nothing to do when the result type is inferred.
2817 static void printShuffleType(AsmPrinter &printer, Operation *op, Type v1Type,
2818  Type resType, DenseI32ArrayAttr mask) {}
2819 
2820 LogicalResult ShuffleVectorOp::verify() {
2821  if (LLVM::isScalableVectorType(getV1().getType()) &&
2822  llvm::any_of(getMask(), [](int32_t v) { return v != 0; }))
2823  return emitOpError("expected a splat operation for scalable vectors");
2824  return success();
2825 }
2826 
2827 //===----------------------------------------------------------------------===//
2828 // Implementations for LLVM::LLVMFuncOp.
2829 //===----------------------------------------------------------------------===//
2830 
2831 // Add the entry block to the function.
2832 Block *LLVMFuncOp::addEntryBlock(OpBuilder &builder) {
2833  assert(empty() && "function already has an entry block");
2834  OpBuilder::InsertionGuard g(builder);
2835  Block *entry = builder.createBlock(&getBody());
2836 
2837  // FIXME: Allow passing in proper locations for the entry arguments.
2838  LLVMFunctionType type = getFunctionType();
2839  for (unsigned i = 0, e = type.getNumParams(); i < e; ++i)
2840  entry->addArgument(type.getParamType(i), getLoc());
2841  return entry;
2842 }
2843 
2844 void LLVMFuncOp::build(OpBuilder &builder, OperationState &result,
2845  StringRef name, Type type, LLVM::Linkage linkage,
2846  bool dsoLocal, CConv cconv, SymbolRefAttr comdat,
2848  ArrayRef<DictionaryAttr> argAttrs,
2849  std::optional<uint64_t> functionEntryCount) {
2850  result.addRegion();
2852  builder.getStringAttr(name));
2853  result.addAttribute(getFunctionTypeAttrName(result.name),
2854  TypeAttr::get(type));
2855  result.addAttribute(getLinkageAttrName(result.name),
2856  LinkageAttr::get(builder.getContext(), linkage));
2857  result.addAttribute(getCConvAttrName(result.name),
2858  CConvAttr::get(builder.getContext(), cconv));
2859  result.attributes.append(attrs.begin(), attrs.end());
2860  if (dsoLocal)
2861  result.addAttribute(getDsoLocalAttrName(result.name),
2862  builder.getUnitAttr());
2863  if (comdat)
2864  result.addAttribute(getComdatAttrName(result.name), comdat);
2865  if (functionEntryCount)
2866  result.addAttribute(getFunctionEntryCountAttrName(result.name),
2867  builder.getI64IntegerAttr(functionEntryCount.value()));
2868  if (argAttrs.empty())
2869  return;
2870 
2871  assert(llvm::cast<LLVMFunctionType>(type).getNumParams() == argAttrs.size() &&
2872  "expected as many argument attribute lists as arguments");
2874  builder, result, argAttrs, /*resultAttrs=*/{},
2875  getArgAttrsAttrName(result.name), getResAttrsAttrName(result.name));
2876 }
2877 
2878 // Builds an LLVM function type from the given lists of input and output types.
2879 // Returns a null type if any of the types provided are non-LLVM types, or if
2880 // there is more than one output type.
2881 static Type
2883  ArrayRef<Type> outputs,
2885  Builder &b = parser.getBuilder();
2886  if (outputs.size() > 1) {
2887  parser.emitError(loc, "failed to construct function type: expected zero or "
2888  "one function result");
2889  return {};
2890  }
2891 
2892  // Convert inputs to LLVM types, exit early on error.
2893  SmallVector<Type, 4> llvmInputs;
2894  for (auto t : inputs) {
2895  if (!isCompatibleType(t)) {
2896  parser.emitError(loc, "failed to construct function type: expected LLVM "
2897  "type for function arguments");
2898  return {};
2899  }
2900  llvmInputs.push_back(t);
2901  }
2902 
2903  // No output is denoted as "void" in LLVM type system.
2904  Type llvmOutput =
2905  outputs.empty() ? LLVMVoidType::get(b.getContext()) : outputs.front();
2906  if (!isCompatibleType(llvmOutput)) {
2907  parser.emitError(loc, "failed to construct function type: expected LLVM "
2908  "type for function results")
2909  << llvmOutput;
2910  return {};
2911  }
2912  return LLVMFunctionType::get(llvmOutput, llvmInputs,
2913  variadicFlag.isVariadic());
2914 }
2915 
2916 // Parses an LLVM function.
2917 //
2918 // operation ::= `llvm.func` linkage? cconv? function-signature
2919 // (`comdat(` symbol-ref-id `)`)?
2920 // function-attributes?
2921 // function-body
2922 //
2923 ParseResult LLVMFuncOp::parse(OpAsmParser &parser, OperationState &result) {
2924  // Default to external linkage if no keyword is provided.
2925  result.addAttribute(getLinkageAttrName(result.name),
2926  LinkageAttr::get(parser.getContext(),
2927  parseOptionalLLVMKeyword<Linkage>(
2928  parser, LLVM::Linkage::External)));
2929 
2930  // Parse optional visibility, default to Default.
2931  result.addAttribute(getVisibility_AttrName(result.name),
2932  parser.getBuilder().getI64IntegerAttr(
2933  parseOptionalLLVMKeyword<LLVM::Visibility, int64_t>(
2934  parser, LLVM::Visibility::Default)));
2935 
2936  // Parse optional UnnamedAddr, default to None.
2937  result.addAttribute(getUnnamedAddrAttrName(result.name),
2938  parser.getBuilder().getI64IntegerAttr(
2939  parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
2940  parser, LLVM::UnnamedAddr::None)));
2941 
2942  // Default to C Calling Convention if no keyword is provided.
2943  result.addAttribute(
2944  getCConvAttrName(result.name),
2945  CConvAttr::get(parser.getContext(),
2946  parseOptionalLLVMKeyword<CConv>(parser, LLVM::CConv::C)));
2947 
2948  StringAttr nameAttr;
2950  SmallVector<DictionaryAttr> resultAttrs;
2951  SmallVector<Type> resultTypes;
2952  bool isVariadic;
2953 
2954  auto signatureLocation = parser.getCurrentLocation();
2955  if (parser.parseSymbolName(nameAttr, SymbolTable::getSymbolAttrName(),
2956  result.attributes) ||
2958  parser, /*allowVariadic=*/true, entryArgs, isVariadic, resultTypes,
2959  resultAttrs))
2960  return failure();
2961 
2962  SmallVector<Type> argTypes;
2963  for (auto &arg : entryArgs)
2964  argTypes.push_back(arg.type);
2965  auto type =
2966  buildLLVMFunctionType(parser, signatureLocation, argTypes, resultTypes,
2968  if (!type)
2969  return failure();
2970  result.addAttribute(getFunctionTypeAttrName(result.name),
2971  TypeAttr::get(type));
2972 
2973  if (succeeded(parser.parseOptionalKeyword("vscale_range"))) {
2974  int64_t minRange, maxRange;
2975  if (parser.parseLParen() || parser.parseInteger(minRange) ||
2976  parser.parseComma() || parser.parseInteger(maxRange) ||
2977  parser.parseRParen())
2978  return failure();
2979  auto intTy = IntegerType::get(parser.getContext(), 32);
2980  result.addAttribute(
2981  getVscaleRangeAttrName(result.name),
2983  IntegerAttr::get(intTy, minRange),
2984  IntegerAttr::get(intTy, maxRange)));
2985  }
2986  // Parse the optional comdat selector.
2987  if (succeeded(parser.parseOptionalKeyword("comdat"))) {
2988  SymbolRefAttr comdat;
2989  if (parser.parseLParen() || parser.parseAttribute(comdat) ||
2990  parser.parseRParen())
2991  return failure();
2992 
2993  result.addAttribute(getComdatAttrName(result.name), comdat);
2994  }
2995 
2997  return failure();
2999  parser.getBuilder(), result, entryArgs, resultAttrs,
3000  getArgAttrsAttrName(result.name), getResAttrsAttrName(result.name));
3001 
3002  auto *body = result.addRegion();
3003  OptionalParseResult parseResult =
3004  parser.parseOptionalRegion(*body, entryArgs);
3005  return failure(parseResult.has_value() && failed(*parseResult));
3006 }
3007 
3008 // Print the LLVMFuncOp. Collects argument and result types and passes them to
3009 // helper functions. Drops "void" result since it cannot be parsed back. Skips
3010 // the external linkage since it is the default value.
3012  p << ' ';
3013  if (getLinkage() != LLVM::Linkage::External)
3014  p << stringifyLinkage(getLinkage()) << ' ';
3015  StringRef visibility = stringifyVisibility(getVisibility_());
3016  if (!visibility.empty())
3017  p << visibility << ' ';
3018  if (auto unnamedAddr = getUnnamedAddr()) {
3019  StringRef str = stringifyUnnamedAddr(*unnamedAddr);
3020  if (!str.empty())
3021  p << str << ' ';
3022  }
3023  if (getCConv() != LLVM::CConv::C)
3024  p << stringifyCConv(getCConv()) << ' ';
3025 
3026  p.printSymbolName(getName());
3027 
3028  LLVMFunctionType fnType = getFunctionType();
3029  SmallVector<Type, 8> argTypes;
3030  SmallVector<Type, 1> resTypes;
3031  argTypes.reserve(fnType.getNumParams());
3032  for (unsigned i = 0, e = fnType.getNumParams(); i < e; ++i)
3033  argTypes.push_back(fnType.getParamType(i));
3034 
3035  Type returnType = fnType.getReturnType();
3036  if (!llvm::isa<LLVMVoidType>(returnType))
3037  resTypes.push_back(returnType);
3038 
3040  isVarArg(), resTypes);
3041 
3042  // Print vscale range if present
3043  if (std::optional<VScaleRangeAttr> vscale = getVscaleRange())
3044  p << " vscale_range(" << vscale->getMinRange().getInt() << ", "
3045  << vscale->getMaxRange().getInt() << ')';
3046 
3047  // Print the optional comdat selector.
3048  if (auto comdat = getComdat())
3049  p << " comdat(" << *comdat << ')';
3050 
3052  p, *this,
3053  {getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
3054  getLinkageAttrName(), getCConvAttrName(), getVisibility_AttrName(),
3055  getComdatAttrName(), getUnnamedAddrAttrName(),
3056  getVscaleRangeAttrName()});
3057 
3058  // Print the body if this is not an external function.
3059  Region &body = getBody();
3060  if (!body.empty()) {
3061  p << ' ';
3062  p.printRegion(body, /*printEntryBlockArgs=*/false,
3063  /*printBlockTerminators=*/true);
3064  }
3065 }
3066 
3067 // Verifies LLVM- and implementation-specific properties of the LLVM func Op:
3068 // - functions don't have 'common' linkage
3069 // - external functions have 'external' or 'extern_weak' linkage;
3070 // - vararg is (currently) only supported for external functions;
3071 LogicalResult LLVMFuncOp::verify() {
3072  if (getLinkage() == LLVM::Linkage::Common)
3073  return emitOpError() << "functions cannot have '"
3074  << stringifyLinkage(LLVM::Linkage::Common)
3075  << "' linkage";
3076 
3077  if (failed(verifyComdat(*this, getComdat())))
3078  return failure();
3079 
3080  if (isExternal()) {
3081  if (getLinkage() != LLVM::Linkage::External &&
3082  getLinkage() != LLVM::Linkage::ExternWeak)
3083  return emitOpError() << "external functions must have '"
3084  << stringifyLinkage(LLVM::Linkage::External)
3085  << "' or '"
3086  << stringifyLinkage(LLVM::Linkage::ExternWeak)
3087  << "' linkage";
3088  return success();
3089  }
3090 
3091  // In LLVM IR, these attributes are composed by convention, not by design.
3092  if (isNoInline() && isAlwaysInline())
3093  return emitError("no_inline and always_inline attributes are incompatible");
3094 
3095  if (isOptimizeNone() && !isNoInline())
3096  return emitOpError("with optimize_none must also be no_inline");
3097 
3098  Type landingpadResultTy;
3099  StringRef diagnosticMessage;
3100  bool isLandingpadTypeConsistent =
3101  !walk([&](Operation *op) {
3102  const auto checkType = [&](Type type, StringRef errorMessage) {
3103  if (!landingpadResultTy) {
3104  landingpadResultTy = type;
3105  return WalkResult::advance();
3106  }
3107  if (landingpadResultTy != type) {
3108  diagnosticMessage = errorMessage;
3109  return WalkResult::interrupt();
3110  }
3111  return WalkResult::advance();
3112  };
3114  .Case<LandingpadOp>([&](auto landingpad) {
3115  constexpr StringLiteral errorMessage =
3116  "'llvm.landingpad' should have a consistent result type "
3117  "inside a function";
3118  return checkType(landingpad.getType(), errorMessage);
3119  })
3120  .Case<ResumeOp>([&](auto resume) {
3121  constexpr StringLiteral errorMessage =
3122  "'llvm.resume' should have a consistent input type inside a "
3123  "function";
3124  return checkType(resume.getValue().getType(), errorMessage);
3125  })
3126  .Default([](auto) { return WalkResult::skip(); });
3127  }).wasInterrupted();
3128  if (!isLandingpadTypeConsistent) {
3129  assert(!diagnosticMessage.empty() &&
3130  "Expecting a non-empty diagnostic message");
3131  return emitError(diagnosticMessage);
3132  }
3133 
3134  if (failed(verifyBlockTags(*this)))
3135  return failure();
3136 
3137  return success();
3138 }
3139 
3140 /// Verifies LLVM- and implementation-specific properties of the LLVM func Op:
3141 /// - entry block arguments are of LLVM types.
3142 LogicalResult LLVMFuncOp::verifyRegions() {
3143  if (isExternal())
3144  return success();
3145 
3146  unsigned numArguments = getFunctionType().getNumParams();
3147  Block &entryBlock = front();
3148  for (unsigned i = 0; i < numArguments; ++i) {
3149  Type argType = entryBlock.getArgument(i).getType();
3150  if (!isCompatibleType(argType))
3151  return emitOpError("entry block argument #")
3152  << i << " is not of LLVM type";
3153  }
3154 
3155  return success();
3156 }
3157 
3158 Region *LLVMFuncOp::getCallableRegion() {
3159  if (isExternal())
3160  return nullptr;
3161  return &getBody();
3162 }
3163 
3164 //===----------------------------------------------------------------------===//
3165 // UndefOp.
3166 //===----------------------------------------------------------------------===//
3167 
3168 /// Fold an undef operation to a dedicated undef attribute.
3169 OpFoldResult LLVM::UndefOp::fold(FoldAdaptor) {
3170  return LLVM::UndefAttr::get(getContext());
3171 }
3172 
3173 //===----------------------------------------------------------------------===//
3174 // PoisonOp.
3175 //===----------------------------------------------------------------------===//
3176 
3177 /// Fold a poison operation to a dedicated poison attribute.
3178 OpFoldResult LLVM::PoisonOp::fold(FoldAdaptor) {
3180 }
3181 
3182 //===----------------------------------------------------------------------===//
3183 // ZeroOp.
3184 //===----------------------------------------------------------------------===//
3185 
3186 LogicalResult LLVM::ZeroOp::verify() {
3187  if (auto targetExtType = dyn_cast<LLVMTargetExtType>(getType()))
3188  if (!targetExtType.hasProperty(LLVM::LLVMTargetExtType::HasZeroInit))
3189  return emitOpError()
3190  << "target extension type does not support zero-initializer";
3191 
3192  return success();
3193 }
3194 
3195 /// Fold a zero operation to a builtin zero attribute when possible and fall
3196 /// back to a dedicated zero attribute.
3197 OpFoldResult LLVM::ZeroOp::fold(FoldAdaptor) {
3199  if (result)
3200  return result;
3201  return LLVM::ZeroAttr::get(getContext());
3202 }
3203 
3204 //===----------------------------------------------------------------------===//
3205 // ConstantOp.
3206 //===----------------------------------------------------------------------===//
3207 
3208 /// Compute the total number of elements in the given type, also taking into
3209 /// account nested types. Supported types are `VectorType` and `LLVMArrayType`.
3210 /// Everything else is treated as a scalar.
3211 static int64_t getNumElements(Type t) {
3212  if (auto vecType = dyn_cast<VectorType>(t)) {
3213  assert(!vecType.isScalable() &&
3214  "number of elements of a scalable vector type is unknown");
3215  return vecType.getNumElements() * getNumElements(vecType.getElementType());
3216  }
3217  if (auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3218  return arrayType.getNumElements() *
3219  getNumElements(arrayType.getElementType());
3220  return 1;
3221 }
3222 
3223 /// Determine the element type of `type`. Supported types are `VectorType`,
3224 /// `TensorType`, and `LLVMArrayType`. Everything else is treated as a scalar.
3225 static Type getElementType(Type type) {
3226  while (auto arrayType = dyn_cast<LLVM::LLVMArrayType>(type))
3227  type = arrayType.getElementType();
3228  if (auto vecType = dyn_cast<VectorType>(type))
3229  return vecType.getElementType();
3230  if (auto tenType = dyn_cast<TensorType>(type))
3231  return tenType.getElementType();
3232  return type;
3233 }
3234 
3235 /// Check if the given type is a scalable vector type or a vector/array type
3236 /// that contains a nested scalable vector type.
3237 static bool hasScalableVectorType(Type t) {
3238  if (auto vecType = dyn_cast<VectorType>(t)) {
3239  if (vecType.isScalable())
3240  return true;
3241  return hasScalableVectorType(vecType.getElementType());
3242  }
3243  if (auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3244  return hasScalableVectorType(arrayType.getElementType());
3245  return false;
3246 }
3247 
3248 /// Verifies the constant array represented by `arrayAttr` matches the provided
3249 /// `arrayType`.
3250 static LogicalResult verifyStructArrayConstant(LLVM::ConstantOp op,
3251  LLVM::LLVMArrayType arrayType,
3252  ArrayAttr arrayAttr, int dim) {
3253  if (arrayType.getNumElements() != arrayAttr.size())
3254  return op.emitOpError()
3255  << "array attribute size does not match array type size in "
3256  "dimension "
3257  << dim << ": " << arrayAttr.size() << " vs. "
3258  << arrayType.getNumElements();
3259 
3260  llvm::DenseSet<Attribute> elementsVerified;
3261 
3262  // Recursively verify sub-dimensions for multidimensional arrays.
3263  if (auto subArrayType =
3264  dyn_cast<LLVM::LLVMArrayType>(arrayType.getElementType())) {
3265  for (auto [idx, elementAttr] : llvm::enumerate(arrayAttr))
3266  if (elementsVerified.insert(elementAttr).second) {
3267  if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3268  continue;
3269  auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3270  if (!subArrayAttr)
3271  return op.emitOpError()
3272  << "nested attribute for sub-array in dimension " << dim
3273  << " at index " << idx
3274  << " must be a zero, or undef, or array attribute";
3275  if (failed(verifyStructArrayConstant(op, subArrayType, subArrayAttr,
3276  dim + 1)))
3277  return failure();
3278  }
3279  return success();
3280  }
3281 
3282  // Forbid usages of ArrayAttr for simple array types that should use
3283  // DenseElementsAttr instead. Note that there would be a use case for such
3284  // array types when one element value is obtained via a ptr-to-int conversion
3285  // from a symbol and cannot be represented in a DenseElementsAttr, but no MLIR
3286  // user needs this so far, and it seems better to avoid people misusing the
3287  // ArrayAttr for simple types.
3288  auto structType = dyn_cast<LLVM::LLVMStructType>(arrayType.getElementType());
3289  if (!structType)
3290  return op.emitOpError() << "for array with an array attribute must have a "
3291  "struct element type";
3292 
3293  // Shallow verification that leaf attributes are appropriate as struct initial
3294  // value.
3295  size_t numStructElements = structType.getBody().size();
3296  for (auto [idx, elementAttr] : llvm::enumerate(arrayAttr)) {
3297  if (elementsVerified.insert(elementAttr).second) {
3298  if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3299  continue;
3300  auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3301  if (!subArrayAttr)
3302  return op.emitOpError()
3303  << "nested attribute for struct element at index " << idx
3304  << " must be a zero, or undef, or array attribute";
3305  if (subArrayAttr.size() != numStructElements)
3306  return op.emitOpError()
3307  << "nested array attribute size for struct element at index "
3308  << idx << " must match struct size: " << subArrayAttr.size()
3309  << " vs. " << numStructElements;
3310  }
3311  }
3312 
3313  return success();
3314 }
3315 
3316 LogicalResult LLVM::ConstantOp::verify() {
3317  if (StringAttr sAttr = llvm::dyn_cast<StringAttr>(getValue())) {
3318  auto arrayType = llvm::dyn_cast<LLVMArrayType>(getType());
3319  if (!arrayType || arrayType.getNumElements() != sAttr.getValue().size() ||
3320  !arrayType.getElementType().isInteger(8)) {
3321  return emitOpError() << "expected array type of "
3322  << sAttr.getValue().size()
3323  << " i8 elements for the string constant";
3324  }
3325  return success();
3326  }
3327  if (auto structType = dyn_cast<LLVMStructType>(getType())) {
3328  auto arrayAttr = dyn_cast<ArrayAttr>(getValue());
3329  if (!arrayAttr)
3330  return emitOpError() << "expected array attribute for struct type";
3331 
3332  ArrayRef<Type> elementTypes = structType.getBody();
3333  if (arrayAttr.size() != elementTypes.size()) {
3334  return emitOpError() << "expected array attribute of size "
3335  << elementTypes.size();
3336  }
3337  for (auto [i, attr, type] : llvm::enumerate(arrayAttr, elementTypes)) {
3338  if (!type.isSignlessIntOrIndexOrFloat()) {
3339  return emitOpError() << "expected struct element types to be floating "
3340  "point type or integer type";
3341  }
3342  if (!isa<FloatAttr, IntegerAttr>(attr)) {
3343  return emitOpError() << "expected element of array attribute to be "
3344  "floating point or integer";
3345  }
3346  if (cast<TypedAttr>(attr).getType() != type)
3347  return emitOpError()
3348  << "struct element at index " << i << " is of wrong type";
3349  }
3350 
3351  return success();
3352  }
3353  if (auto targetExtType = dyn_cast<LLVMTargetExtType>(getType()))
3354  return emitOpError() << "does not support target extension type.";
3355 
3356  // Check that an attribute whose element type has floating point semantics
3357  // `attributeFloatSemantics` is compatible with a type whose element type
3358  // is `constantElementType`.
3359  //
3360  // Requirement is that either
3361  // 1) They have identical floating point types.
3362  // 2) `constantElementType` is an integer type of the same width as the float
3363  // attribute. This is to support builtin MLIR float types without LLVM
3364  // equivalents, see comments in getLLVMConstant for more details.
3365  auto verifyFloatSemantics =
3366  [this](const llvm::fltSemantics &attributeFloatSemantics,
3367  Type constantElementType) -> LogicalResult {
3368  if (auto floatType = dyn_cast<FloatType>(constantElementType)) {
3369  if (&floatType.getFloatSemantics() != &attributeFloatSemantics) {
3370  return emitOpError()
3371  << "attribute and type have different float semantics";
3372  }
3373  return success();
3374  }
3375  unsigned floatWidth = APFloat::getSizeInBits(attributeFloatSemantics);
3376  if (isa<IntegerType>(constantElementType)) {
3377  if (!constantElementType.isInteger(floatWidth))
3378  return emitOpError() << "expected integer type of width " << floatWidth;
3379 
3380  return success();
3381  }
3382  return success();
3383  };
3384 
3385  // Verification of IntegerAttr, FloatAttr, ElementsAttr, ArrayAttr.
3386  if (isa<IntegerAttr>(getValue())) {
3387  if (!llvm::isa<IntegerType>(getType()))
3388  return emitOpError() << "expected integer type";
3389  } else if (auto floatAttr = dyn_cast<FloatAttr>(getValue())) {
3390  return verifyFloatSemantics(floatAttr.getValue().getSemantics(), getType());
3391  } else if (auto elementsAttr = dyn_cast<ElementsAttr>(getValue())) {
3392  if (hasScalableVectorType(getType())) {
3393  // The exact number of elements of a scalable vector is unknown, so we
3394  // allow only splat attributes.
3395  auto splatElementsAttr = dyn_cast<SplatElementsAttr>(getValue());
3396  if (!splatElementsAttr)
3397  return emitOpError()
3398  << "scalable vector type requires a splat attribute";
3399  return success();
3400  }
3401  if (!isa<VectorType, LLVM::LLVMArrayType>(getType()))
3402  return emitOpError() << "expected vector or array type";
3403 
3404  // The number of elements of the attribute and the type must match.
3405  int64_t attrNumElements = elementsAttr.getNumElements();
3406  if (getNumElements(getType()) != attrNumElements) {
3407  return emitOpError()
3408  << "type and attribute have a different number of elements: "
3409  << getNumElements(getType()) << " vs. " << attrNumElements;
3410  }
3411 
3412  Type attrElmType = getElementType(elementsAttr.getType());
3413  Type resultElmType = getElementType(getType());
3414  if (auto floatType = dyn_cast<FloatType>(attrElmType))
3415  return verifyFloatSemantics(floatType.getFloatSemantics(), resultElmType);
3416 
3417  if (isa<IntegerType>(attrElmType) && !isa<IntegerType>(resultElmType)) {
3418  return emitOpError(
3419  "expected integer element type for integer elements attribute");
3420  }
3421  } else if (auto arrayAttr = dyn_cast<ArrayAttr>(getValue())) {
3422 
3423  // The case where the constant is LLVMStructType has already been handled.
3424  auto arrayType = dyn_cast<LLVM::LLVMArrayType>(getType());
3425  if (!arrayType)
3426  return emitOpError()
3427  << "expected array or struct type for array attribute";
3428 
3429  // When the attribute is an ArrayAttr, check that its nesting matches the
3430  // corresponding ArrayType or VectorType nesting.
3431  return verifyStructArrayConstant(*this, arrayType, arrayAttr, /*dim=*/0);
3432  } else {
3433  return emitOpError()
3434  << "only supports integer, float, string or elements attributes";
3435  }
3436 
3437  return success();
3438 }
3439 
3440 bool LLVM::ConstantOp::isBuildableWith(Attribute value, Type type) {
3441  // The value's type must be the same as the provided type.
3442  auto typedAttr = dyn_cast<TypedAttr>(value);
3443  if (!typedAttr || typedAttr.getType() != type || !isCompatibleType(type))
3444  return false;
3445  // The value's type must be an LLVM compatible type.
3446  if (!isCompatibleType(type))
3447  return false;
3448  // TODO: Add support for additional attributes kinds once needed.
3449  return isa<IntegerAttr, FloatAttr, ElementsAttr>(value);
3450 }
3451 
3452 ConstantOp LLVM::ConstantOp::materialize(OpBuilder &builder, Attribute value,
3453  Type type, Location loc) {
3454  if (isBuildableWith(value, type))
3455  return LLVM::ConstantOp::create(builder, loc, cast<TypedAttr>(value));
3456  return nullptr;
3457 }
3458 
3459 // Constant op constant-folds to its value.
3460 OpFoldResult LLVM::ConstantOp::fold(FoldAdaptor) { return getValue(); }
3461 
3462 //===----------------------------------------------------------------------===//
3463 // AtomicRMWOp
3464 //===----------------------------------------------------------------------===//
3465 
3466 void AtomicRMWOp::build(OpBuilder &builder, OperationState &state,
3467  AtomicBinOp binOp, Value ptr, Value val,
3468  AtomicOrdering ordering, StringRef syncscope,
3469  unsigned alignment, bool isVolatile) {
3470  build(builder, state, val.getType(), binOp, ptr, val, ordering,
3471  !syncscope.empty() ? builder.getStringAttr(syncscope) : nullptr,
3472  alignment ? builder.getI64IntegerAttr(alignment) : nullptr, isVolatile,
3473  /*access_groups=*/nullptr,
3474  /*alias_scopes=*/nullptr, /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr);
3475 }
3476 
3477 LogicalResult AtomicRMWOp::verify() {
3478  auto valType = getVal().getType();
3479  if (getBinOp() == AtomicBinOp::fadd || getBinOp() == AtomicBinOp::fsub ||
3480  getBinOp() == AtomicBinOp::fmin || getBinOp() == AtomicBinOp::fmax ||
3481  getBinOp() == AtomicBinOp::fminimum ||
3482  getBinOp() == AtomicBinOp::fmaximum) {
3483  if (isCompatibleVectorType(valType)) {
3484  if (isScalableVectorType(valType))
3485  return emitOpError("expected LLVM IR fixed vector type");
3486  Type elemType = llvm::cast<VectorType>(valType).getElementType();
3487  if (!isCompatibleFloatingPointType(elemType))
3488  return emitOpError(
3489  "expected LLVM IR floating point type for vector element");
3490  } else if (!isCompatibleFloatingPointType(valType)) {
3491  return emitOpError("expected LLVM IR floating point type");
3492  }
3493  } else if (getBinOp() == AtomicBinOp::xchg) {
3494  DataLayout dataLayout = DataLayout::closest(*this);
3495  if (!isTypeCompatibleWithAtomicOp(valType, dataLayout))
3496  return emitOpError("unexpected LLVM IR type for 'xchg' bin_op");
3497  } else {
3498  auto intType = llvm::dyn_cast<IntegerType>(valType);
3499  unsigned intBitWidth = intType ? intType.getWidth() : 0;
3500  if (intBitWidth != 8 && intBitWidth != 16 && intBitWidth != 32 &&
3501  intBitWidth != 64)
3502  return emitOpError("expected LLVM IR integer type");
3503  }
3504 
3505  if (static_cast<unsigned>(getOrdering()) <
3506  static_cast<unsigned>(AtomicOrdering::monotonic))
3507  return emitOpError() << "expected at least '"
3508  << stringifyAtomicOrdering(AtomicOrdering::monotonic)
3509  << "' ordering";
3510 
3511  return success();
3512 }
3513 
3514 //===----------------------------------------------------------------------===//
3515 // AtomicCmpXchgOp
3516 //===----------------------------------------------------------------------===//
3517 
3518 /// Returns an LLVM struct type that contains a value type and a boolean type.
3519 static LLVMStructType getValAndBoolStructType(Type valType) {
3520  auto boolType = IntegerType::get(valType.getContext(), 1);
3521  return LLVMStructType::getLiteral(valType.getContext(), {valType, boolType});
3522 }
3523 
3524 void AtomicCmpXchgOp::build(OpBuilder &builder, OperationState &state,
3525  Value ptr, Value cmp, Value val,
3526  AtomicOrdering successOrdering,
3527  AtomicOrdering failureOrdering, StringRef syncscope,
3528  unsigned alignment, bool isWeak, bool isVolatile) {
3529  build(builder, state, getValAndBoolStructType(val.getType()), ptr, cmp, val,
3530  successOrdering, failureOrdering,
3531  !syncscope.empty() ? builder.getStringAttr(syncscope) : nullptr,
3532  alignment ? builder.getI64IntegerAttr(alignment) : nullptr, isWeak,
3533  isVolatile, /*access_groups=*/nullptr,
3534  /*alias_scopes=*/nullptr, /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr);
3535 }
3536 
3537 LogicalResult AtomicCmpXchgOp::verify() {
3538  auto ptrType = llvm::cast<LLVM::LLVMPointerType>(getPtr().getType());
3539  if (!ptrType)
3540  return emitOpError("expected LLVM IR pointer type for operand #0");
3541  auto valType = getVal().getType();
3542  DataLayout dataLayout = DataLayout::closest(*this);
3543  if (!isTypeCompatibleWithAtomicOp(valType, dataLayout))
3544  return emitOpError("unexpected LLVM IR type");
3545  if (getSuccessOrdering() < AtomicOrdering::monotonic ||
3546  getFailureOrdering() < AtomicOrdering::monotonic)
3547  return emitOpError("ordering must be at least 'monotonic'");
3548  if (getFailureOrdering() == AtomicOrdering::release ||
3549  getFailureOrdering() == AtomicOrdering::acq_rel)
3550  return emitOpError("failure ordering cannot be 'release' or 'acq_rel'");
3551  return success();
3552 }
3553 
3554 //===----------------------------------------------------------------------===//
3555 // FenceOp
3556 //===----------------------------------------------------------------------===//
3557 
3558 void FenceOp::build(OpBuilder &builder, OperationState &state,
3559  AtomicOrdering ordering, StringRef syncscope) {
3560  build(builder, state, ordering,
3561  syncscope.empty() ? nullptr : builder.getStringAttr(syncscope));
3562 }
3563 
3564 LogicalResult FenceOp::verify() {
3565  if (getOrdering() == AtomicOrdering::not_atomic ||
3566  getOrdering() == AtomicOrdering::unordered ||
3567  getOrdering() == AtomicOrdering::monotonic)
3568  return emitOpError("can be given only acquire, release, acq_rel, "
3569  "and seq_cst orderings");
3570  return success();
3571 }
3572 
3573 //===----------------------------------------------------------------------===//
3574 // Verifier for extension ops
3575 //===----------------------------------------------------------------------===//
3576 
3577 /// Verifies that the given extension operation operates on consistent scalars
3578 /// or vectors, and that the target width is larger than the input width.
3579 template <class ExtOp>
3580 static LogicalResult verifyExtOp(ExtOp op) {
3581  IntegerType inputType, outputType;
3582  if (isCompatibleVectorType(op.getArg().getType())) {
3583  if (!isCompatibleVectorType(op.getResult().getType()))
3584  return op.emitError(
3585  "input type is a vector but output type is an integer");
3586  if (getVectorNumElements(op.getArg().getType()) !=
3587  getVectorNumElements(op.getResult().getType()))
3588  return op.emitError("input and output vectors are of incompatible shape");
3589  // Because this is a CastOp, the element of vectors is guaranteed to be an
3590  // integer.
3591  inputType = cast<IntegerType>(
3592  cast<VectorType>(op.getArg().getType()).getElementType());
3593  outputType = cast<IntegerType>(
3594  cast<VectorType>(op.getResult().getType()).getElementType());
3595  } else {
3596  // Because this is a CastOp and arg is not a vector, arg is guaranteed to be
3597  // an integer.
3598  inputType = cast<IntegerType>(op.getArg().getType());
3599  outputType = dyn_cast<IntegerType>(op.getResult().getType());
3600  if (!outputType)
3601  return op.emitError(
3602  "input type is an integer but output type is a vector");
3603  }
3604 
3605  if (outputType.getWidth() <= inputType.getWidth())
3606  return op.emitError("integer width of the output type is smaller or "
3607  "equal to the integer width of the input type");
3608  return success();
3609 }
3610 
3611 //===----------------------------------------------------------------------===//
3612 // ZExtOp
3613 //===----------------------------------------------------------------------===//
3614 
3615 LogicalResult ZExtOp::verify() { return verifyExtOp<ZExtOp>(*this); }
3616 
3617 OpFoldResult LLVM::ZExtOp::fold(FoldAdaptor adaptor) {
3618  auto arg = dyn_cast_or_null<IntegerAttr>(adaptor.getArg());
3619  if (!arg)
3620  return {};
3621 
3622  size_t targetSize = cast<IntegerType>(getType()).getWidth();
3623  return IntegerAttr::get(getType(), arg.getValue().zext(targetSize));
3624 }
3625 
3626 //===----------------------------------------------------------------------===//
3627 // SExtOp
3628 //===----------------------------------------------------------------------===//
3629 
3630 LogicalResult SExtOp::verify() { return verifyExtOp<SExtOp>(*this); }
3631 
3632 //===----------------------------------------------------------------------===//
3633 // Folder and verifier for LLVM::BitcastOp
3634 //===----------------------------------------------------------------------===//
3635 
3636 /// Folds a cast op that can be chained.
3637 template <typename T>
3639  typename T::FoldAdaptor adaptor) {
3640  // cast(x : T0, T0) -> x
3641  if (castOp.getArg().getType() == castOp.getType())
3642  return castOp.getArg();
3643  if (auto prev = castOp.getArg().template getDefiningOp<T>()) {
3644  // cast(cast(x : T0, T1), T0) -> x
3645  if (prev.getArg().getType() == castOp.getType())
3646  return prev.getArg();
3647  // cast(cast(x : T0, T1), T2) -> cast(x: T0, T2)
3648  castOp.getArgMutable().set(prev.getArg());
3649  return Value{castOp};
3650  }
3651  return {};
3652 }
3653 
3654 OpFoldResult LLVM::BitcastOp::fold(FoldAdaptor adaptor) {
3655  return foldChainableCast(*this, adaptor);
3656 }
3657 
3658 LogicalResult LLVM::BitcastOp::verify() {
3659  auto resultType = llvm::dyn_cast<LLVMPointerType>(
3660  extractVectorElementType(getResult().getType()));
3661  auto sourceType = llvm::dyn_cast<LLVMPointerType>(
3662  extractVectorElementType(getArg().getType()));
3663 
3664  // If one of the types is a pointer (or vector of pointers), then
3665  // both source and result type have to be pointers.
3666  if (static_cast<bool>(resultType) != static_cast<bool>(sourceType))
3667  return emitOpError("can only cast pointers from and to pointers");
3668 
3669  if (!resultType)
3670  return success();
3671 
3672  auto isVector = llvm::IsaPred<VectorType>;
3673 
3674  // Due to bitcast requiring both operands to be of the same size, it is not
3675  // possible for only one of the two to be a pointer of vectors.
3676  if (isVector(getResult().getType()) && !isVector(getArg().getType()))
3677  return emitOpError("cannot cast pointer to vector of pointers");
3678 
3679  if (!isVector(getResult().getType()) && isVector(getArg().getType()))
3680  return emitOpError("cannot cast vector of pointers to pointer");
3681 
3682  // Bitcast cannot cast between pointers of different address spaces.
3683  // 'llvm.addrspacecast' must be used for this purpose instead.
3684  if (resultType.getAddressSpace() != sourceType.getAddressSpace())
3685  return emitOpError("cannot cast pointers of different address spaces, "
3686  "use 'llvm.addrspacecast' instead");
3687 
3688  return success();
3689 }
3690 
3691 //===----------------------------------------------------------------------===//
3692 // Folder for LLVM::AddrSpaceCastOp
3693 //===----------------------------------------------------------------------===//
3694 
3695 OpFoldResult LLVM::AddrSpaceCastOp::fold(FoldAdaptor adaptor) {
3696  return foldChainableCast(*this, adaptor);
3697 }
3698 
3699 Value LLVM::AddrSpaceCastOp::getViewSource() { return getArg(); }
3700 
3701 //===----------------------------------------------------------------------===//
3702 // Folder for LLVM::GEPOp
3703 //===----------------------------------------------------------------------===//
3704 
3705 OpFoldResult LLVM::GEPOp::fold(FoldAdaptor adaptor) {
3706  GEPIndicesAdaptor<ArrayRef<Attribute>> indices(getRawConstantIndicesAttr(),
3707  adaptor.getDynamicIndices());
3708 
3709  // gep %x:T, 0 -> %x
3710  if (getBase().getType() == getType() && indices.size() == 1)
3711  if (auto integer = llvm::dyn_cast_or_null<IntegerAttr>(indices[0]))
3712  if (integer.getValue().isZero())
3713  return getBase();
3714 
3715  // Canonicalize any dynamic indices of constant value to constant indices.
3716  bool changed = false;
3717  SmallVector<GEPArg> gepArgs;
3718  for (auto iter : llvm::enumerate(indices)) {
3719  auto integer = llvm::dyn_cast_or_null<IntegerAttr>(iter.value());
3720  // Constant indices can only be int32_t, so if integer does not fit we
3721  // are forced to keep it dynamic, despite being a constant.
3722  if (!indices.isDynamicIndex(iter.index()) || !integer ||
3723  !integer.getValue().isSignedIntN(kGEPConstantBitWidth)) {
3724 
3725  PointerUnion<IntegerAttr, Value> existing = getIndices()[iter.index()];
3726  if (Value val = llvm::dyn_cast_if_present<Value>(existing))
3727  gepArgs.emplace_back(val);
3728  else
3729  gepArgs.emplace_back(cast<IntegerAttr>(existing).getInt());
3730 
3731  continue;
3732  }
3733 
3734  changed = true;
3735  gepArgs.emplace_back(integer.getInt());
3736  }
3737  if (changed) {
3738  SmallVector<int32_t> rawConstantIndices;
3739  SmallVector<Value> dynamicIndices;
3740  destructureIndices(getElemType(), gepArgs, rawConstantIndices,
3741  dynamicIndices);
3742 
3743  getDynamicIndicesMutable().assign(dynamicIndices);
3744  setRawConstantIndices(rawConstantIndices);
3745  return Value{*this};
3746  }
3747 
3748  return {};
3749 }
3750 
3751 Value LLVM::GEPOp::getViewSource() { return getBase(); }
3752 
3753 //===----------------------------------------------------------------------===//
3754 // ShlOp
3755 //===----------------------------------------------------------------------===//
3756 
3757 OpFoldResult LLVM::ShlOp::fold(FoldAdaptor adaptor) {
3758  auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3759  if (!rhs)
3760  return {};
3761 
3762  if (rhs.getValue().getZExtValue() >=
3763  getLhs().getType().getIntOrFloatBitWidth())
3764  return {}; // TODO: Fold into poison.
3765 
3766  auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3767  if (!lhs)
3768  return {};
3769 
3770  return IntegerAttr::get(getType(), lhs.getValue().shl(rhs.getValue()));
3771 }
3772 
3773 //===----------------------------------------------------------------------===//
3774 // OrOp
3775 //===----------------------------------------------------------------------===//
3776 
3777 OpFoldResult LLVM::OrOp::fold(FoldAdaptor adaptor) {
3778  auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3779  if (!lhs)
3780  return {};
3781 
3782  auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3783  if (!rhs)
3784  return {};
3785 
3786  return IntegerAttr::get(getType(), lhs.getValue() | rhs.getValue());
3787 }
3788 
3789 //===----------------------------------------------------------------------===//
3790 // CallIntrinsicOp
3791 //===----------------------------------------------------------------------===//
3792 
3793 LogicalResult CallIntrinsicOp::verify() {
3794  if (!getIntrin().starts_with("llvm."))
3795  return emitOpError() << "intrinsic name must start with 'llvm.'";
3796  if (failed(verifyOperandBundles(*this)))
3797  return failure();
3798  return success();
3799 }
3800 
3801 void CallIntrinsicOp::build(OpBuilder &builder, OperationState &state,
3802  mlir::StringAttr intrin, mlir::ValueRange args) {
3803  build(builder, state, /*resultTypes=*/TypeRange{}, intrin, args,
3804  FastmathFlagsAttr{},
3805  /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{}, /*arg_attrs=*/{},
3806  /*res_attrs=*/{});
3807 }
3808 
3809 void CallIntrinsicOp::build(OpBuilder &builder, OperationState &state,
3810  mlir::StringAttr intrin, mlir::ValueRange args,
3811  mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
3812  build(builder, state, /*resultTypes=*/TypeRange{}, intrin, args,
3813  fastMathFlags,
3814  /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{}, /*arg_attrs=*/{},
3815  /*res_attrs=*/{});
3816 }
3817 
3818 void CallIntrinsicOp::build(OpBuilder &builder, OperationState &state,
3819  mlir::Type resultType, mlir::StringAttr intrin,
3820  mlir::ValueRange args) {
3821  build(builder, state, {resultType}, intrin, args, FastmathFlagsAttr{},
3822  /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{}, /*arg_attrs=*/{},
3823  /*res_attrs=*/{});
3824 }
3825 
3826 void CallIntrinsicOp::build(OpBuilder &builder, OperationState &state,
3827  mlir::TypeRange resultTypes,
3828  mlir::StringAttr intrin, mlir::ValueRange args,
3829  mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
3830  build(builder, state, resultTypes, intrin, args, fastMathFlags,
3831  /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{}, /*arg_attrs=*/{},
3832  /*res_attrs=*/{});
3833 }
3834 
3835 ParseResult CallIntrinsicOp::parse(OpAsmParser &parser,
3836  OperationState &result) {
3837  StringAttr intrinAttr;
3840  SmallVector<SmallVector<Type>> opBundleOperandTypes;
3841  ArrayAttr opBundleTags;
3842 
3843  // Parse intrinsic name.
3845  intrinAttr, parser.getBuilder().getType<NoneType>()))
3846  return failure();
3847  result.addAttribute(CallIntrinsicOp::getIntrinAttrName(result.name),
3848  intrinAttr);
3849 
3850  if (parser.parseLParen())
3851  return failure();
3852 
3853  // Parse the function arguments.
3854  if (parser.parseOperandList(operands))
3855  return mlir::failure();
3856 
3857  if (parser.parseRParen())
3858  return mlir::failure();
3859 
3860  // Handle bundles.
3861  SMLoc opBundlesLoc = parser.getCurrentLocation();
3862  if (std::optional<ParseResult> result = parseOpBundles(
3863  parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
3864  result && failed(*result))
3865  return failure();
3866  if (opBundleTags && !opBundleTags.empty())
3867  result.addAttribute(
3868  CallIntrinsicOp::getOpBundleTagsAttrName(result.name).getValue(),
3869  opBundleTags);
3870 
3871  if (parser.parseOptionalAttrDict(result.attributes))
3872  return mlir::failure();
3873 
3874  SmallVector<DictionaryAttr> argAttrs;
3875  SmallVector<DictionaryAttr> resultAttrs;
3876  if (parseCallTypeAndResolveOperands(parser, result, /*isDirect=*/true,
3877  operands, argAttrs, resultAttrs))
3878  return failure();
3880  parser.getBuilder(), result, argAttrs, resultAttrs,
3881  getArgAttrsAttrName(result.name), getResAttrsAttrName(result.name));
3882 
3883  if (resolveOpBundleOperands(parser, opBundlesLoc, result, opBundleOperands,
3884  opBundleOperandTypes,
3885  getOpBundleSizesAttrName(result.name)))
3886  return failure();
3887 
3888  int32_t numOpBundleOperands = 0;
3889  for (const auto &operands : opBundleOperands)
3890  numOpBundleOperands += operands.size();
3891 
3892  result.addAttribute(
3893  CallIntrinsicOp::getOperandSegmentSizeAttr(),
3895  {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
3896 
3897  return mlir::success();
3898 }
3899 
3901  p << ' ';
3902  p.printAttributeWithoutType(getIntrinAttr());
3903 
3904  OperandRange args = getArgs();
3905  p << "(" << args << ")";
3906 
3907  // Operand bundles.
3908  if (!getOpBundleOperands().empty()) {
3909  p << ' ';
3910  printOpBundles(p, *this, getOpBundleOperands(),
3911  getOpBundleOperands().getTypes(), getOpBundleTagsAttr());
3912  }
3913 
3914  p.printOptionalAttrDict(processFMFAttr((*this)->getAttrs()),
3915  {getOperandSegmentSizesAttrName(),
3916  getOpBundleSizesAttrName(), getIntrinAttrName(),
3917  getOpBundleTagsAttrName(), getArgAttrsAttrName(),
3918  getResAttrsAttrName()});
3919 
3920  p << " : ";
3921 
3922  // Reconstruct the MLIR function type from operand and result types.
3924  p, args.getTypes(), getArgAttrsAttr(),
3925  /*isVariadic=*/false, getResultTypes(), getResAttrsAttr());
3926 }
3927 
3928 //===----------------------------------------------------------------------===//
3929 // LinkerOptionsOp
3930 //===----------------------------------------------------------------------===//
3931 
3932 LogicalResult LinkerOptionsOp::verify() {
3933  if (mlir::Operation *parentOp = (*this)->getParentOp();
3934  parentOp && !satisfiesLLVMModule(parentOp))
3935  return emitOpError("must appear at the module level");
3936  return success();
3937 }
3938 
3939 //===----------------------------------------------------------------------===//
3940 // ModuleFlagsOp
3941 //===----------------------------------------------------------------------===//
3942 
3943 LogicalResult ModuleFlagsOp::verify() {
3944  if (Operation *parentOp = (*this)->getParentOp();
3945  parentOp && !satisfiesLLVMModule(parentOp))
3946  return emitOpError("must appear at the module level");
3947  for (Attribute flag : getFlags())
3948  if (!isa<ModuleFlagAttr>(flag))
3949  return emitOpError("expected a module flag attribute");
3950  return success();
3951 }
3952 
3953 //===----------------------------------------------------------------------===//
3954 // InlineAsmOp
3955 //===----------------------------------------------------------------------===//
3956 
3957 void InlineAsmOp::getEffects(
3959  &effects) {
3960  if (getHasSideEffects()) {
3961  effects.emplace_back(MemoryEffects::Write::get());
3962  effects.emplace_back(MemoryEffects::Read::get());
3963  }
3964 }
3965 
3966 //===----------------------------------------------------------------------===//
3967 // BlockAddressOp
3968 //===----------------------------------------------------------------------===//
3969 
3970 LogicalResult
3971 BlockAddressOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
3972  Operation *symbol = symbolTable.lookupSymbolIn(parentLLVMModule(*this),
3973  getBlockAddr().getFunction());
3974  auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
3975 
3976  if (!function)
3977  return emitOpError("must reference a function defined by 'llvm.func'");
3978 
3979  return success();
3980 }
3981 
3982 LLVMFuncOp BlockAddressOp::getFunction(SymbolTableCollection &symbolTable) {
3983  return dyn_cast_or_null<LLVMFuncOp>(symbolTable.lookupSymbolIn(
3984  parentLLVMModule(*this), getBlockAddr().getFunction()));
3985 }
3986 
3987 BlockTagOp BlockAddressOp::getBlockTagOp() {
3988  auto funcOp = dyn_cast<LLVMFuncOp>(mlir::SymbolTable::lookupNearestSymbolFrom(
3989  parentLLVMModule(*this), getBlockAddr().getFunction()));
3990  if (!funcOp)
3991  return nullptr;
3992 
3993  BlockTagOp blockTagOp = nullptr;
3994  funcOp.walk([&](LLVM::BlockTagOp labelOp) {
3995  if (labelOp.getTag() == getBlockAddr().getTag()) {
3996  blockTagOp = labelOp;
3997  return WalkResult::interrupt();
3998  }
3999  return WalkResult::advance();
4000  });
4001  return blockTagOp;
4002 }
4003 
4004 LogicalResult BlockAddressOp::verify() {
4005  if (!getBlockTagOp())
4006  return emitOpError(
4007  "expects an existing block label target in the referenced function");
4008 
4009  return success();
4010 }
4011 
4012 /// Fold a blockaddress operation to a dedicated blockaddress
4013 /// attribute.
4014 OpFoldResult BlockAddressOp::fold(FoldAdaptor) { return getBlockAddr(); }
4015 
4016 //===----------------------------------------------------------------------===//
4017 // LLVM::IndirectBrOp
4018 //===----------------------------------------------------------------------===//
4019 
4021  assert(index < getNumSuccessors() && "invalid successor index");
4022  return SuccessorOperands(getSuccOperandsMutable()[index]);
4023 }
4024 
4025 void IndirectBrOp::build(OpBuilder &odsBuilder, OperationState &odsState,
4026  Value addr, ArrayRef<ValueRange> succOperands,
4027  BlockRange successors) {
4028  odsState.addOperands(addr);
4029  for (ValueRange range : succOperands)
4030  odsState.addOperands(range);
4031  SmallVector<int32_t> rangeSegments;
4032  for (ValueRange range : succOperands)
4033  rangeSegments.push_back(range.size());
4034  odsState.getOrAddProperties<Properties>().indbr_operand_segments =
4035  odsBuilder.getDenseI32ArrayAttr(rangeSegments);
4036  odsState.addSuccessors(successors);
4037 }
4038 
4039 static ParseResult parseIndirectBrOpSucessors(
4040  OpAsmParser &parser, Type &flagType,
4041  SmallVectorImpl<Block *> &succOperandBlocks,
4043  SmallVectorImpl<SmallVector<Type>> &succOperandsTypes) {
4044  if (failed(parser.parseCommaSeparatedList(
4046  [&]() {
4047  Block *destination = nullptr;
4048  SmallVector<OpAsmParser::UnresolvedOperand> operands;
4049  SmallVector<Type> operandTypes;
4050 
4051  if (parser.parseSuccessor(destination).failed())
4052  return failure();
4053 
4054  if (succeeded(parser.parseOptionalLParen())) {
4055  if (failed(parser.parseOperandList(
4056  operands, OpAsmParser::Delimiter::None)) ||
4057  failed(parser.parseColonTypeList(operandTypes)) ||
4058  failed(parser.parseRParen()))
4059  return failure();
4060  }
4061  succOperandBlocks.push_back(destination);
4062  succOperands.emplace_back(operands);
4063  succOperandsTypes.emplace_back(operandTypes);
4064  return success();
4065  },
4066  "successor blocks")))
4067  return failure();
4068  return success();
4069 }
4070 
4071 static void
4072 printIndirectBrOpSucessors(OpAsmPrinter &p, IndirectBrOp op, Type flagType,
4073  SuccessorRange succs, OperandRangeRange succOperands,
4074  const TypeRangeRange &succOperandsTypes) {
4075  p << "[";
4076  llvm::interleave(
4077  llvm::zip(succs, succOperands),
4078  [&](auto i) {
4079  p.printNewline();
4080  p.printSuccessorAndUseList(std::get<0>(i), std::get<1>(i));
4081  },
4082  [&] { p << ','; });
4083  if (!succOperands.empty())
4084  p.printNewline();
4085  p << "]";
4086 }
4087 
4088 //===----------------------------------------------------------------------===//
4089 // AssumeOp (intrinsic)
4090 //===----------------------------------------------------------------------===//
4091 
4092 void LLVM::AssumeOp::build(OpBuilder &builder, OperationState &state,
4093  mlir::Value cond) {
4094  return build(builder, state, cond, /*op_bundle_operands=*/{},
4095  /*op_bundle_tags=*/ArrayAttr{});
4096 }
4097 
4098 void LLVM::AssumeOp::build(OpBuilder &builder, OperationState &state,
4099  Value cond, llvm::StringRef tag, ValueRange args) {
4100  return build(builder, state, cond, ArrayRef<ValueRange>(args),
4101  builder.getStrArrayAttr(tag));
4102 }
4103 
4104 void LLVM::AssumeOp::build(OpBuilder &builder, OperationState &state,
4105  Value cond, AssumeAlignTag, Value ptr, Value align) {
4106  return build(builder, state, cond, "align", ValueRange{ptr, align});
4107 }
4108 
4109 void LLVM::AssumeOp::build(OpBuilder &builder, OperationState &state,
4110  Value cond, AssumeSeparateStorageTag, Value ptr1,
4111  Value ptr2) {
4112  return build(builder, state, cond, "separate_storage",
4113  ValueRange{ptr1, ptr2});
4114 }
4115 
4116 LogicalResult LLVM::AssumeOp::verify() { return verifyOperandBundles(*this); }
4117 
4118 //===----------------------------------------------------------------------===//
4119 // masked_gather (intrinsic)
4120 //===----------------------------------------------------------------------===//
4121 
4122 LogicalResult LLVM::masked_gather::verify() {
4123  auto ptrsVectorType = getPtrs().getType();
4124  Type expectedPtrsVectorType =
4126  LLVM::getVectorNumElements(getRes().getType()));
4127  // Vector of pointers type should match result vector type, other than the
4128  // element type.
4129  if (ptrsVectorType != expectedPtrsVectorType)
4130  return emitOpError("expected operand #1 type to be ")
4131  << expectedPtrsVectorType;
4132  return success();
4133 }
4134 
4135 //===----------------------------------------------------------------------===//
4136 // masked_scatter (intrinsic)
4137 //===----------------------------------------------------------------------===//
4138 
4139 LogicalResult LLVM::masked_scatter::verify() {
4140  auto ptrsVectorType = getPtrs().getType();
4141  Type expectedPtrsVectorType =
4143  LLVM::getVectorNumElements(getValue().getType()));
4144  // Vector of pointers type should match value vector type, other than the
4145  // element type.
4146  if (ptrsVectorType != expectedPtrsVectorType)
4147  return emitOpError("expected operand #2 type to be ")
4148  << expectedPtrsVectorType;
4149  return success();
4150 }
4151 
4152 //===----------------------------------------------------------------------===//
4153 // masked_expandload (intrinsic)
4154 //===----------------------------------------------------------------------===//
4155 
4156 void LLVM::masked_expandload::build(OpBuilder &builder, OperationState &state,
4157  mlir::TypeRange resTys, Value ptr,
4158  Value mask, Value passthru,
4159  uint64_t align) {
4160  ArrayAttr argAttrs = getLLVMAlignParamForCompressExpand(builder, true, align);
4161  build(builder, state, resTys, ptr, mask, passthru, /*arg_attrs=*/argAttrs,
4162  /*res_attrs=*/nullptr);
4163 }
4164 
4165 //===----------------------------------------------------------------------===//
4166 // masked_compressstore (intrinsic)
4167 //===----------------------------------------------------------------------===//
4168 
4169 void LLVM::masked_compressstore::build(OpBuilder &builder,
4170  OperationState &state, Value value,
4171  Value ptr, Value mask, uint64_t align) {
4172  ArrayAttr argAttrs =
4173  getLLVMAlignParamForCompressExpand(builder, false, align);
4174  build(builder, state, value, ptr, mask, /*arg_attrs=*/argAttrs,
4175  /*res_attrs=*/nullptr);
4176 }
4177 
4178 //===----------------------------------------------------------------------===//
4179 // InlineAsmOp
4180 //===----------------------------------------------------------------------===//
4181 
4182 LogicalResult InlineAsmOp::verify() {
4183  if (!getTailCallKindAttr())
4184  return success();
4185 
4186  if (getTailCallKindAttr().getTailCallKind() == TailCallKind::MustTail)
4187  return emitOpError(
4188  "tail call kind 'musttail' is not supported by this operation");
4189 
4190  return success();
4191 }
4192 
4193 //===----------------------------------------------------------------------===//
4194 // LLVMDialect initialization, type parsing, and registration.
4195 //===----------------------------------------------------------------------===//
4196 
4197 void LLVMDialect::initialize() {
4198  registerAttributes();
4199 
4200  // clang-format off
4201  addTypes<LLVMVoidType,
4202  LLVMTokenType,
4203  LLVMLabelType,
4204  LLVMMetadataType>();
4205  // clang-format on
4206  registerTypes();
4207 
4208  addOperations<
4209 #define GET_OP_LIST
4210 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
4211 
4212  ,
4213 #define GET_OP_LIST
4214 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
4215 
4216  >();
4217 
4218  // Support unknown operations because not all LLVM operations are registered.
4219  allowUnknownOperations();
4220  declarePromisedInterface<DialectInlinerInterface, LLVMDialect>();
4221 }
4222 
4223 #define GET_OP_CLASSES
4224 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
4225 
4226 #define GET_OP_CLASSES
4227 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
4228 
4229 LogicalResult LLVMDialect::verifyDataLayoutString(
4230  StringRef descr, llvm::function_ref<void(const Twine &)> reportError) {
4231  llvm::Expected<llvm::DataLayout> maybeDataLayout =
4232  llvm::DataLayout::parse(descr);
4233  if (maybeDataLayout)
4234  return success();
4235 
4236  std::string message;
4237  llvm::raw_string_ostream messageStream(message);
4238  llvm::logAllUnhandledErrors(maybeDataLayout.takeError(), messageStream);
4239  reportError("invalid data layout descriptor: " + message);
4240  return failure();
4241 }
4242 
4243 /// Verify LLVM dialect attributes.
4244 LogicalResult LLVMDialect::verifyOperationAttribute(Operation *op,
4245  NamedAttribute attr) {
4246  // If the data layout attribute is present, it must use the LLVM data layout
4247  // syntax. Try parsing it and report errors in case of failure. Users of this
4248  // attribute may assume it is well-formed and can pass it to the (asserting)
4249  // llvm::DataLayout constructor.
4250  if (attr.getName() != LLVM::LLVMDialect::getDataLayoutAttrName())
4251  return success();
4252  if (auto stringAttr = llvm::dyn_cast<StringAttr>(attr.getValue()))
4253  return verifyDataLayoutString(
4254  stringAttr.getValue(),
4255  [op](const Twine &message) { op->emitOpError() << message.str(); });
4256 
4257  return op->emitOpError() << "expected '"
4258  << LLVM::LLVMDialect::getDataLayoutAttrName()
4259  << "' to be a string attributes";
4260 }
4261 
4262 LogicalResult LLVMDialect::verifyParameterAttribute(Operation *op,
4263  Type paramType,
4264  NamedAttribute paramAttr) {
4265  // LLVM attribute may be attached to a result of operation that has not been
4266  // converted to LLVM dialect yet, so the result may have a type with unknown
4267  // representation in LLVM dialect type space. In this case we cannot verify
4268  // whether the attribute may be
4269  bool verifyValueType = isCompatibleType(paramType);
4270  StringAttr name = paramAttr.getName();
4271 
4272  auto checkUnitAttrType = [&]() -> LogicalResult {
4273  if (!llvm::isa<UnitAttr>(paramAttr.getValue()))
4274  return op->emitError() << name << " should be a unit attribute";
4275  return success();
4276  };
4277  auto checkTypeAttrType = [&]() -> LogicalResult {
4278  if (!llvm::isa<TypeAttr>(paramAttr.getValue()))
4279  return op->emitError() << name << " should be a type attribute";
4280  return success();
4281  };
4282  auto checkIntegerAttrType = [&]() -> LogicalResult {
4283  if (!llvm::isa<IntegerAttr>(paramAttr.getValue()))
4284  return op->emitError() << name << " should be an integer attribute";
4285  return success();
4286  };
4287  auto checkPointerType = [&]() -> LogicalResult {
4288  if (!llvm::isa<LLVMPointerType>(paramType))
4289  return op->emitError()
4290  << name << " attribute attached to non-pointer LLVM type";
4291  return success();
4292  };
4293  auto checkIntegerType = [&]() -> LogicalResult {
4294  if (!llvm::isa<IntegerType>(paramType))
4295  return op->emitError()
4296  << name << " attribute attached to non-integer LLVM type";
4297  return success();
4298  };
4299  auto checkPointerTypeMatches = [&]() -> LogicalResult {
4300  if (failed(checkPointerType()))
4301  return failure();
4302 
4303  return success();
4304  };
4305 
4306  // Check a unit attribute that is attached to a pointer value.
4307  if (name == LLVMDialect::getNoAliasAttrName() ||
4308  name == LLVMDialect::getReadonlyAttrName() ||
4309  name == LLVMDialect::getReadnoneAttrName() ||
4310  name == LLVMDialect::getWriteOnlyAttrName() ||
4311  name == LLVMDialect::getNestAttrName() ||
4312  name == LLVMDialect::getNoCaptureAttrName() ||
4313  name == LLVMDialect::getNoFreeAttrName() ||
4314  name == LLVMDialect::getNonNullAttrName()) {
4315  if (failed(checkUnitAttrType()))
4316  return failure();
4317  if (verifyValueType && failed(checkPointerType()))
4318  return failure();
4319  return success();
4320  }
4321 
4322  // Check a type attribute that is attached to a pointer value.
4323  if (name == LLVMDialect::getStructRetAttrName() ||
4324  name == LLVMDialect::getByValAttrName() ||
4325  name == LLVMDialect::getByRefAttrName() ||
4326  name == LLVMDialect::getElementTypeAttrName() ||
4327  name == LLVMDialect::getInAllocaAttrName() ||
4328  name == LLVMDialect::getPreallocatedAttrName()) {
4329  if (failed(checkTypeAttrType()))
4330  return failure();
4331  if (verifyValueType && failed(checkPointerTypeMatches()))
4332  return failure();
4333  return success();
4334  }
4335 
4336  // Check a unit attribute that is attached to an integer value.
4337  if (name == LLVMDialect::getSExtAttrName() ||
4338  name == LLVMDialect::getZExtAttrName()) {
4339  if (failed(checkUnitAttrType()))
4340  return failure();
4341  if (verifyValueType && failed(checkIntegerType()))
4342  return failure();
4343  return success();
4344  }
4345 
4346  // Check an integer attribute that is attached to a pointer value.
4347  if (name == LLVMDialect::getAlignAttrName() ||
4348  name == LLVMDialect::getDereferenceableAttrName() ||
4349  name == LLVMDialect::getDereferenceableOrNullAttrName()) {
4350  if (failed(checkIntegerAttrType()))
4351  return failure();
4352  if (verifyValueType && failed(checkPointerType()))
4353  return failure();
4354  return success();
4355  }
4356 
4357  // Check an integer attribute that is attached to a pointer value.
4358  if (name == LLVMDialect::getStackAlignmentAttrName()) {
4359  if (failed(checkIntegerAttrType()))
4360  return failure();
4361  return success();
4362  }
4363 
4364  // Check a unit attribute that can be attached to arbitrary types.
4365  if (name == LLVMDialect::getNoUndefAttrName() ||
4366  name == LLVMDialect::getInRegAttrName() ||
4367  name == LLVMDialect::getReturnedAttrName())
4368  return checkUnitAttrType();
4369 
4370  return success();
4371 }
4372 
4373 /// Verify LLVMIR function argument attributes.
4374 LogicalResult LLVMDialect::verifyRegionArgAttribute(Operation *op,
4375  unsigned regionIdx,
4376  unsigned argIdx,
4377  NamedAttribute argAttr) {
4378  auto funcOp = dyn_cast<FunctionOpInterface>(op);
4379  if (!funcOp)
4380  return success();
4381  Type argType = funcOp.getArgumentTypes()[argIdx];
4382 
4383  return verifyParameterAttribute(op, argType, argAttr);
4384 }
4385 
4386 LogicalResult LLVMDialect::verifyRegionResultAttribute(Operation *op,
4387  unsigned regionIdx,
4388  unsigned resIdx,
4389  NamedAttribute resAttr) {
4390  auto funcOp = dyn_cast<FunctionOpInterface>(op);
4391  if (!funcOp)
4392  return success();
4393  Type resType = funcOp.getResultTypes()[resIdx];
4394 
4395  // Check to see if this function has a void return with a result attribute
4396  // to it. It isn't clear what semantics we would assign to that.
4397  if (llvm::isa<LLVMVoidType>(resType))
4398  return op->emitError() << "cannot attach result attributes to functions "
4399  "with a void return";
4400 
4401  // Check to see if this attribute is allowed as a result attribute. Only
4402  // explicitly forbidden LLVM attributes will cause an error.
4403  auto name = resAttr.getName();
4404  if (name == LLVMDialect::getAllocAlignAttrName() ||
4405  name == LLVMDialect::getAllocatedPointerAttrName() ||
4406  name == LLVMDialect::getByValAttrName() ||
4407  name == LLVMDialect::getByRefAttrName() ||
4408  name == LLVMDialect::getInAllocaAttrName() ||
4409  name == LLVMDialect::getNestAttrName() ||
4410  name == LLVMDialect::getNoCaptureAttrName() ||
4411  name == LLVMDialect::getNoFreeAttrName() ||
4412  name == LLVMDialect::getPreallocatedAttrName() ||
4413  name == LLVMDialect::getReadnoneAttrName() ||
4414  name == LLVMDialect::getReadonlyAttrName() ||
4415  name == LLVMDialect::getReturnedAttrName() ||
4416  name == LLVMDialect::getStackAlignmentAttrName() ||
4417  name == LLVMDialect::getStructRetAttrName() ||
4418  name == LLVMDialect::getWriteOnlyAttrName())
4419  return op->emitError() << name << " is not a valid result attribute";
4420  return verifyParameterAttribute(op, resType, resAttr);
4421 }
4422 
4424  Type type, Location loc) {
4425  // If this was folded from an operation other than llvm.mlir.constant, it
4426  // should be materialized as such. Note that an llvm.mlir.zero may fold into
4427  // a builtin zero attribute and thus will materialize as a llvm.mlir.constant.
4428  if (auto symbol = dyn_cast<FlatSymbolRefAttr>(value))
4429  if (isa<LLVM::LLVMPointerType>(type))
4430  return LLVM::AddressOfOp::create(builder, loc, type, symbol);
4431  if (isa<LLVM::UndefAttr>(value))
4432  return LLVM::UndefOp::create(builder, loc, type);
4433  if (isa<LLVM::PoisonAttr>(value))
4434  return LLVM::PoisonOp::create(builder, loc, type);
4435  if (isa<LLVM::ZeroAttr>(value))
4436  return LLVM::ZeroOp::create(builder, loc, type);
4437  // Otherwise try materializing it as a regular llvm.mlir.constant op.
4438  return LLVM::ConstantOp::materialize(builder, value, type, loc);
4439 }
4440 
4441 //===----------------------------------------------------------------------===//
4442 // Utility functions.
4443 //===----------------------------------------------------------------------===//
4444 
4446  StringRef name, StringRef value,
4447  LLVM::Linkage linkage) {
4448  assert(builder.getInsertionBlock() &&
4449  builder.getInsertionBlock()->getParentOp() &&
4450  "expected builder to point to a block constrained in an op");
4451  auto module =
4452  builder.getInsertionBlock()->getParentOp()->getParentOfType<ModuleOp>();
4453  assert(module && "builder points to an op outside of a module");
4454 
4455  // Create the global at the entry of the module.
4456  OpBuilder moduleBuilder(module.getBodyRegion(), builder.getListener());
4457  MLIRContext *ctx = builder.getContext();
4458  auto type = LLVM::LLVMArrayType::get(IntegerType::get(ctx, 8), value.size());
4459  auto global = LLVM::GlobalOp::create(
4460  moduleBuilder, loc, type, /*isConstant=*/true, linkage, name,
4461  builder.getStringAttr(value), /*alignment=*/0);
4462 
4463  LLVMPointerType ptrType = LLVMPointerType::get(ctx);
4464  // Get the pointer to the first character in the global string.
4465  Value globalPtr =
4466  LLVM::AddressOfOp::create(builder, loc, ptrType, global.getSymNameAttr());
4467  return LLVM::GEPOp::create(builder, loc, ptrType, type, globalPtr,
4468  ArrayRef<GEPArg>{0, 0});
4469 }
4470 
4472  return op->hasTrait<OpTrait::SymbolTable>() &&
4474 }
4475 
4477  Operation *module = op->getParentOp();
4478  while (module && !satisfiesLLVMModule(module))
4479  module = module->getParentOp();
4480  assert(module && "unexpected operation outside of a module");
4481  return module;
4482 }
static OperandRange getSuccessorOperands(Block *block, unsigned successorIndex)
Return the operand range used to transfer operands from block to its successor with the given index.
Definition: CFGToSCF.cpp:140
static Value getBase(Value v)
Looks through known "view-like" ops to find the base memref.
static Operation * materializeConstant(Dialect *dialect, OpBuilder &builder, Attribute value, Type type, Location loc)
A utility function used to materialize a constant for a given attribute and type.
Definition: FoldUtils.cpp:50
static MLIRContext * getContext(OpFoldResult val)
static int parseOptionalKeywordAlternative(OpAsmParser &parser, ArrayRef< StringRef > keywords)
Definition: LLVMDialect.cpp:90
static ArrayAttr getLLVMAlignParamForCompressExpand(OpBuilder &builder, bool isExpandLoad, uint64_t alignment=1)
static LogicalResult verifyAtomicMemOp(OpTy memOp, Type valueType, ArrayRef< AtomicOrdering > unsupportedOrderings)
Verifies the attributes and the type of atomic memory access operations.
static RetTy parseOptionalLLVMKeyword(OpAsmParser &parser, EnumTy defaultValue)
Parse an enum from the keyword, or default to the provided default value.
static LogicalResult checkGlobalXtorData(Operation *op, ArrayAttr data)
static ParseResult parseGEPIndices(OpAsmParser &parser, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &indices, DenseI32ArrayAttr &rawConstantIndices)
static LogicalResult verifyOperandBundles(OpType &op)
static ParseResult parseCmpOp(OpAsmParser &parser, OperationState &result)
static void printOneOpBundle(OpAsmPrinter &p, OperandRange operands, TypeRange operandTypes, StringRef tag)
static LogicalResult verifyComdat(Operation *op, std::optional< SymbolRefAttr > attr)
static LLVMFunctionType getLLVMFuncType(MLIRContext *context, TypeRange results, ValueRange args)
Constructs a LLVMFunctionType from MLIR results and args.
static void printSwitchOpCases(OpAsmPrinter &p, SwitchOp op, Type flagType, DenseIntElementsAttr caseValues, SuccessorRange caseDestinations, OperandRangeRange caseOperands, const TypeRangeRange &caseOperandTypes)
static ParseResult resolveOpBundleOperands(OpAsmParser &parser, SMLoc loc, OperationState &state, ArrayRef< SmallVector< OpAsmParser::UnresolvedOperand >> opBundleOperands, ArrayRef< SmallVector< Type >> opBundleOperandTypes, StringAttr opBundleSizesAttrName)
static LogicalResult verifyCallOpVarCalleeType(OpTy callOp)
Verify that the parameter and return types of the variadic callee type match the callOp argument and ...
static ParseResult parseOptionalCallFuncPtr(OpAsmParser &parser, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &operands)
Parses an optional function pointer operand before the call argument list for indirect calls,...
static bool isZeroAttribute(Attribute value)
static void printGEPIndices(OpAsmPrinter &printer, LLVM::GEPOp gepOp, OperandRange indices, DenseI32ArrayAttr rawConstantIndices)
static LLVMStructType getValAndBoolStructType(Type valType)
Returns an LLVM struct type that contains a value type and a boolean type.
static void printOpBundles(OpAsmPrinter &p, Operation *op, OperandRangeRange opBundleOperands, TypeRangeRange opBundleOperandTypes, std::optional< ArrayAttr > opBundleTags)
static void printShuffleType(AsmPrinter &printer, Operation *op, Type v1Type, Type resType, DenseI32ArrayAttr mask)
Nothing to do when the result type is inferred.
static LogicalResult verifyBlockTags(LLVMFuncOp funcOp)
static Type buildLLVMFunctionType(OpAsmParser &parser, SMLoc loc, ArrayRef< Type > inputs, ArrayRef< Type > outputs, function_interface_impl::VariadicFlag variadicFlag)
static auto processFMFAttr(ArrayRef< NamedAttribute > attrs)
Definition: LLVMDialect.cpp:49
static std::optional< ParseResult > parseOpBundles(OpAsmParser &p, SmallVector< SmallVector< OpAsmParser::UnresolvedOperand >> &opBundleOperands, SmallVector< SmallVector< Type >> &opBundleOperandTypes, ArrayAttr &opBundleTags)
static ParseResult parseSwitchOpCases(OpAsmParser &parser, Type flagType, DenseIntElementsAttr &caseValues, SmallVectorImpl< Block * > &caseDestinations, SmallVectorImpl< SmallVector< OpAsmParser::UnresolvedOperand >> &caseOperands, SmallVectorImpl< SmallVector< Type >> &caseOperandTypes)
<cases> ::= [ (case (, case )* )? ] <case> ::= integer : bb-id (( ssa-use-and-type-list ))?
static TypeAttr getCallOpVarCalleeType(LLVMFunctionType calleeType)
Gets the variadic callee type for a LLVMFunctionType.
static Type getInsertExtractValueElementType(function_ref< InFlightDiagnostic(StringRef)> emitError, Type containerType, ArrayRef< int64_t > position)
Extract the type at position in the LLVM IR aggregate type containerType.
static Type getElementType(Type type)
Determine the element type of type.
static ParseResult parseOneOpBundle(OpAsmParser &p, SmallVector< SmallVector< OpAsmParser::UnresolvedOperand >> &opBundleOperands, SmallVector< SmallVector< Type >> &opBundleOperandTypes, SmallVector< Attribute > &opBundleTags)
static ParseResult parseIndirectBrOpSucessors(OpAsmParser &parser, Type &flagType, SmallVectorImpl< Block * > &succOperandBlocks, SmallVectorImpl< SmallVector< OpAsmParser::UnresolvedOperand >> &succOperands, SmallVectorImpl< SmallVector< Type >> &succOperandsTypes)
static void printIndirectBrOpSucessors(OpAsmPrinter &p, IndirectBrOp op, Type flagType, SuccessorRange succs, OperandRangeRange succOperands, const TypeRangeRange &succOperandsTypes)
static void printLLVMLinkage(OpAsmPrinter &p, Operation *, LinkageAttr val)
static LogicalResult verifyStructArrayConstant(LLVM::ConstantOp op, LLVM::LLVMArrayType arrayType, ArrayAttr arrayAttr, int dim)
Verifies the constant array represented by arrayAttr matches the provided arrayType.
static ParseResult parseCallTypeAndResolveOperands(OpAsmParser &parser, OperationState &result, bool isDirect, ArrayRef< OpAsmParser::UnresolvedOperand > operands, SmallVectorImpl< DictionaryAttr > &argAttrs, SmallVectorImpl< DictionaryAttr > &resultAttrs)
Parses the type of a call operation and resolves the operands if the parsing succeeds.
static LogicalResult verifySymbolAttrUse(FlatSymbolRefAttr symbol, Operation *op, SymbolTableCollection &symbolTable)
Verifies symbol's use in op to ensure the symbol is a valid and fully defined llvm....
Definition: LLVMDialect.cpp:64
static Type extractVectorElementType(Type type)
Returns the elemental type of any LLVM-compatible vector type or self.
static bool hasScalableVectorType(Type t)
Check if the given type is a scalable vector type or a vector/array type that contains a nested scala...
static OpFoldResult foldChainableCast(T castOp, typename T::FoldAdaptor adaptor)
Folds a cast op that can be chained.
static void destructureIndices(Type currType, ArrayRef< GEPArg > indices, SmallVectorImpl< int32_t > &rawConstantIndices, SmallVectorImpl< Value > &dynamicIndices)
Destructures the 'indices' parameter into 'rawConstantIndices' and 'dynamicIndices',...
static ParseResult parseCommonGlobalAndAlias(OpAsmParser &parser, OperationState &result)
Parse common attributes that might show up in the same order in both GlobalOp and AliasOp.
static SmallVector< Type, 1 > getCallOpResultTypes(LLVMFunctionType calleeType)
Gets the MLIR Op-like result types of a LLVMFunctionType.
static Type getI1SameShape(Type type)
Returns a boolean type that has the same shape as type.
Definition: LLVMDialect.cpp:80
static void printCommonGlobalAndAlias(OpAsmPrinter &p, OpType op)
static ParseResult parseLLVMLinkage(OpAsmParser &p, LinkageAttr &val)
static Attribute getBoolAttribute(Type type, MLIRContext *ctx, bool value)
Returns a scalar or vector boolean attribute of the given type.
static LogicalResult verifyCallOpDebugInfo(CallOp callOp, LLVMFuncOp callee)
Verify that an inlinable callsite of a debug-info-bearing function in a debug-info-bearing function h...
static ParseResult parseShuffleType(AsmParser &parser, Type v1Type, Type &resType, DenseI32ArrayAttr mask)
Build the result type of a shuffle vector operation.
static LogicalResult verifyExtOp(ExtOp op)
Verifies that the given extension operation operates on consistent scalars or vectors,...
static constexpr const char kElemTypeAttrName[]
Definition: LLVMDialect.cpp:47
static ParseResult parseInsertExtractValueElementType(AsmParser &parser, Type &valueType, Type containerType, DenseI64ArrayAttr position)
Infer the value type from the container type and position.
static LogicalResult verifyStructIndices(Type baseGEPType, unsigned indexPos, GEPIndicesAdaptor< ValueRange > indices, function_ref< InFlightDiagnostic()> emitOpError)
For the given indices, check if they comply with baseGEPType, especially check against LLVMStructType...
static int64_t getNumElements(Type t)
Compute the total number of elements in the given type, also taking into account nested types.
static bool isTypeCompatibleWithAtomicOp(Type type, const DataLayout &dataLayout)
Returns true if the given type is supported by atomic operations.
static void printInsertExtractValueElementType(AsmPrinter &printer, Operation *op, Type valueType, Type containerType, DenseI64ArrayAttr position)
Nothing to print for an inferred type.
#define REGISTER_ENUM_TYPE(Ty)
@ None
static std::string diag(const llvm::Value &value)
static Value min(ImplicitLocOpBuilder &builder, Value value, Value bound)
static void print(spirv::VerCapExtAttr triple, DialectAsmPrinter &printer)
static VectorType getVectorType(Type scalarTy, const VectorizationStrategy *strategy)
Returns the vector type resulting from applying the provided vectorization strategy on the scalar typ...
This base class exposes generic asm parser hooks, usable across the various derived parsers.
ParseResult parseSymbolName(StringAttr &result)
Parse an -identifier and store it (without the '@' symbol) in a string attribute.
@ Paren
Parens surrounding zero or more operands.
@ None
Zero or more operands with no delimiters.
@ Square
Square brackets surrounding zero or more operands.
virtual OptionalParseResult parseOptionalInteger(APInt &result)=0
Parse an optional integer value from the stream.
virtual ParseResult parseColonTypeList(SmallVectorImpl< Type > &result)=0
Parse a colon followed by a type list, which must have at least one type.
virtual ParseResult parseCommaSeparatedList(Delimiter delimiter, function_ref< ParseResult()> parseElementFn, StringRef contextMessage=StringRef())=0
Parse a list of comma-separated items with an optional delimiter.
virtual Builder & getBuilder() const =0
Return a builder which provides useful access to MLIRContext, global objects like types and attribute...
virtual ParseResult parseOptionalAttrDict(NamedAttrList &result)=0
Parse a named dictionary into 'result' if it is present.
virtual ParseResult parseOptionalKeyword(StringRef keyword)=0
Parse the given keyword if present.
MLIRContext * getContext() const
Definition: AsmPrinter.cpp:72
virtual ParseResult parseRParen()=0
Parse a ) token.
virtual InFlightDiagnostic emitError(SMLoc loc, const Twine &message={})=0
Emit a diagnostic at the specified location and return failure.
virtual ParseResult parseLSquare()=0
Parse a [ token.
virtual ParseResult parseRSquare()=0
Parse a ] token.
virtual ParseResult parseOptionalColonTypeList(SmallVectorImpl< Type > &result)=0
Parse an optional colon followed by a type list, which if present must have at least one type.
ParseResult parseInteger(IntT &result)
Parse an integer value from the stream.
virtual ParseResult parseOptionalRParen()=0
Parse a ) token if present.
virtual ParseResult parseCustomAttributeWithFallback(Attribute &result, Type type, function_ref< ParseResult(Attribute &result, Type type)> parseAttribute)=0
Parse a custom attribute with the provided callback, unless the next token is #, in which case the ge...
ParseResult parseString(std::string *string)
Parse a quoted string token.
virtual ParseResult parseOptionalAttrDictWithKeyword(NamedAttrList &result)=0
Parse a named dictionary into 'result' if the attributes keyword is present.
virtual SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
virtual ParseResult parseOptionalComma()=0
Parse a , token if present.
virtual ParseResult parseColon()=0
Parse a : token.
virtual SMLoc getNameLoc() const =0
Return the location of the original name token.
virtual ParseResult parseOptionalRSquare()=0
Parse a ] token if present.
virtual ParseResult parseLParen()=0
Parse a ( token.
virtual ParseResult parseType(Type &result)=0
Parse a type.
virtual ParseResult parseComma()=0
Parse a , token.
virtual ParseResult parseOptionalLParen()=0
Parse a ( token if present.
ParseResult parseTypeList(SmallVectorImpl< Type > &result)
Parse a type list.
Definition: AsmPrinter.cpp:77
ParseResult parseKeyword(StringRef keyword)
Parse a given keyword.
virtual ParseResult parseOptionalLSquare()=0
Parse a [ token if present.
virtual ParseResult parseAttribute(Attribute &result, Type type={})=0
Parse an arbitrary attribute of a given type and return it in result.
This base class exposes generic asm printer hooks, usable across the various derived printers.
virtual void printAttributeWithoutType(Attribute attr)
Print the given attribute without its type.
virtual void printSymbolName(StringRef symbolRef)
Print the given string as a symbol reference, i.e.
virtual void printString(StringRef string)
Print the given string as a quoted string, escaping any special or non-printable characters in it.
virtual void printAttribute(Attribute attr)
Attributes are known-constant values of operations.
Definition: Attributes.h:25
This class provides an abstraction over the different types of ranges over Blocks.
Definition: BlockSupport.h:106
Block represents an ordered list of Operations.
Definition: Block.h:33
bool empty()
Definition: Block.h:148
BlockArgument getArgument(unsigned i)
Definition: Block.h:129
Operation * getTerminator()
Get the terminator operation of this block.
Definition: Block.cpp:244
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
Definition: Block.cpp:153
Operation & front()
Definition: Block.h:153
Operation * getParentOp()
Returns the closest surrounding operation that contains this block.
Definition: Block.cpp:31
static BoolAttr get(MLIRContext *context, bool value)
This class is a general helper class for creating context-global objects like types,...
Definition: Builders.h:50
UnitAttr getUnitAttr()
Definition: Builders.cpp:93
IntegerAttr getI32IntegerAttr(int32_t value)
Definition: Builders.cpp:195
DenseI32ArrayAttr getDenseI32ArrayAttr(ArrayRef< int32_t > values)
Definition: Builders.cpp:158
IntegerAttr getI64IntegerAttr(int64_t value)
Definition: Builders.cpp:107
Ty getType(Args &&...args)
Get or construct an instance of the type Ty with provided arguments.
Definition: Builders.h:89
StringAttr getStringAttr(const Twine &bytes)
Definition: Builders.cpp:257
TypedAttr getZeroAttr(Type type)
Definition: Builders.cpp:319
MLIRContext * getContext() const
Definition: Builders.h:55
ArrayAttr getArrayAttr(ArrayRef< Attribute > value)
Definition: Builders.cpp:261
DictionaryAttr getDictionaryAttr(ArrayRef< NamedAttribute > value)
Definition: Builders.cpp:99
NamedAttribute getNamedAttr(StringRef name, Attribute val)
Definition: Builders.cpp:89
ArrayAttr getStrArrayAttr(ArrayRef< StringRef > values)
Definition: Builders.cpp:301
Attr getAttr(Args &&...args)
Get or construct an instance of the attribute Attr with provided arguments.
Definition: Builders.h:96
The main mechanism for performing data layout queries.
static DataLayout closest(Operation *op)
Returns the layout of the closest parent operation carrying layout info.
llvm::TypeSize getTypeSizeInBits(Type t) const
Returns the size in bits of the given type in the current scope.
An attribute that represents a reference to a dense vector or tensor object.
std::enable_if_t<!std::is_base_of< Attribute, T >::value||std::is_same< Attribute, T >::value, T > getSplatValue() const
Return the splat value for this attribute.
auto getValues() const
Return the held element values as a range of the given type.
Type getElementType() const
Return the element type of this DenseElementsAttr.
static DenseElementsAttr get(ShapedType type, ArrayRef< Attribute > values)
Constructs a dense elements attribute from an array of element values.
An attribute that represents a reference to a dense integer vector or tensor object.
static DenseIntElementsAttr get(const ShapedType &type, Arg &&arg)
Get an instance of a DenseIntElementsAttr with the given arguments.
A symbol reference with a reference path containing a single element.
StringRef getValue() const
Returns the name of the held symbol reference.
StringAttr getAttr() const
Returns the name of the held symbol reference as a StringAttr.
This class represents a fused location whose metadata is known to be an instance of the given type.
Definition: Location.h:149
This class represents a diagnostic that is inflight and set to be reported.
Definition: Diagnostics.h:314
Diagnostic & attachNote(std::optional< Location > noteLoc=std::nullopt)
Attaches a note to this diagnostic.
Definition: Diagnostics.h:352
Class used for building a 'llvm.getelementptr'.
Definition: LLVMDialect.h:71
Class used for convenient access and iteration over GEP indices.
Definition: LLVMDialect.h:118
bool isDynamicIndex(size_t index) const
Returns whether the GEP index at the given position is a dynamic index.
Definition: LLVMDialect.h:147
size_t size() const
Returns the amount of indices of the GEPOp.
Definition: LLVMDialect.h:152
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:76
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:63
This class provides a mutable adaptor for a range of operands.
Definition: ValueRange.h:118
std::optional< NamedAttribute > getNamed(StringRef name) const
Return the specified named attribute if present, std::nullopt otherwise.
Attribute erase(StringAttr name)
Erase the attribute with the given name from the list.
void append(StringRef name, Attribute attr)
Add an attribute with the specified name.
Attribute set(StringAttr name, Attribute value)
If the an attribute exists with the specified name, change it to the new value.
NamedAttribute represents a combination of a name and an Attribute value.
Definition: Attributes.h:164
StringAttr getName() const
Return the name of the attribute.
Definition: Attributes.cpp:55
Attribute getValue() const
Return the value of the attribute.
Definition: Attributes.h:179
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
virtual ParseResult parseRegion(Region &region, ArrayRef< Argument > arguments={}, bool enableNameShadowing=false)=0
Parses a region.
virtual ParseResult parseSuccessor(Block *&dest)=0
Parse a single operation successor.
virtual ParseResult resolveOperand(const UnresolvedOperand &operand, Type type, SmallVectorImpl< Value > &result)=0
Resolve an operand to an SSA value, emitting an error on failure.
virtual OptionalParseResult parseOptionalOperand(UnresolvedOperand &result, bool allowResultNumber=true)=0
Parse a single operand if present.
virtual ParseResult parseSuccessorAndUseList(Block *&dest, SmallVectorImpl< Value > &operands)=0
Parse a single operation successor and its operand list.
virtual OptionalParseResult parseOptionalRegion(Region &region, ArrayRef< Argument > arguments={}, bool enableNameShadowing=false)=0
Parses a region if present.
ParseResult resolveOperands(Operands &&operands, Type type, SmallVectorImpl< Value > &result)
Resolve a list of operands to SSA values, emitting an error on failure, or appending the results to t...
virtual ParseResult parseOperand(UnresolvedOperand &result, bool allowResultNumber=true)=0
Parse a single SSA value operand name along with a result number if allowResultNumber is true.
virtual ParseResult parseOperandList(SmallVectorImpl< UnresolvedOperand > &result, Delimiter delimiter=Delimiter::None, bool allowResultNumber=true, int requiredOperandCount=-1)=0
Parse zero or more SSA comma-separated operand references with a specified surrounding delimiter,...
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
virtual void printNewline()=0
Print a newline and indent the printer to the start of the current operation.
virtual void printSuccessorAndUseList(Block *successor, ValueRange succOperands)=0
Print the successor and its operands.
void printOperands(const ContainerType &container)
Print a comma separated list of operands.
virtual void printOptionalAttrDict(ArrayRef< NamedAttribute > attrs, ArrayRef< StringRef > elidedAttrs={})=0
If the specified operation has attributes, print out an attribute dictionary with their values.
virtual void printRegion(Region &blocks, bool printEntryBlockArgs=true, bool printBlockTerminators=true, bool printEmptyBlock=false)=0
Prints a region.
virtual void printOperand(Value value)=0
Print implementations for various things an operation contains.
RAII guard to reset the insertion point of the builder when destroyed.
Definition: Builders.h:346
This class helps build Operations.
Definition: Builders.h:205
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.
Definition: Builders.cpp:425
Listener * getListener() const
Returns the current listener of this builder, or nullptr if this builder doesn't have a listener.
Definition: Builders.h:318
Block * getInsertionBlock() const
Return the block the current insertion point belongs to.
Definition: Builders.h:440
This class represents a single result from folding an operation.
Definition: OpDefinition.h:272
This class provides the API for ops that are known to be isolated from above.
A trait used to provide symbol table functionalities to a region operation.
Definition: SymbolTable.h:452
This class represents a contiguous range of operand ranges, e.g.
Definition: ValueRange.h:84
This class implements the operand iterators for the Operation class.
Definition: ValueRange.h:43
type_range getTypes() const
Definition: ValueRange.cpp:28
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
Definition: Operation.h:749
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
Definition: Operation.h:234
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
Definition: Operation.cpp:267
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
Definition: Operation.h:238
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
Definition: Operation.cpp:672
This class implements Optional functionality for ParseResult.
Definition: OpDefinition.h:40
ParseResult value() const
Access the internal ParseResult value.
Definition: OpDefinition.h:53
bool has_value() const
Returns true if we contain a valid ParseResult value.
Definition: OpDefinition.h:50
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition: Region.h:26
iterator_range< OpIterator > getOps()
Definition: Region.h:172
bool empty()
Definition: Region.h:60
Block & emplaceBlock()
Definition: Region.h:46
This class represents a specific instance of an effect.
static DerivedEffect * get()
Returns a unique instance for the derived effect class.
This class models how operands are forwarded to block arguments in control flow.
This class implements the successor iterators for Block.
Definition: BlockSupport.h:73
This class represents a collection of SymbolTables.
Definition: SymbolTable.h:283
virtual Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
virtual Operation * lookupSymbolIn(Operation *symbolTableOp, StringAttr symbol)
Look up a symbol with the specified name within the specified symbol table operation,...
static StringRef getSymbolAttrName()
Return the name of the attribute used for symbol names.
Definition: SymbolTable.h:76
static Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
This class provides an abstraction for a range of TypeRange.
Definition: TypeRange.h:95
This class provides an abstraction over the various different ranges of value types.
Definition: TypeRange.h:37
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:74
MLIRContext * getContext() const
Return the MLIRContext in which this type was uniqued.
Definition: Types.cpp:35
unsigned getIntOrFloatBitWidth() const
Return the bit width of an integer or a float type, assert failure on other types.
Definition: Types.cpp:122
bool isSignlessIntOrIndexOrFloat() const
Return true if this is a signless integer, index, or float type.
Definition: Types.cpp:104
This class provides an abstraction over the different types of ranges over Values.
Definition: ValueRange.h:387
type_range getTypes() const
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:96
Type getType() const
Return the type of this value.
Definition: Value.h:105
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
Definition: Value.cpp:18
A utility result that is used to signal how to proceed with an ongoing walk:
Definition: WalkResult.h:29
static WalkResult skip()
Definition: WalkResult.h:48
static WalkResult advance()
Definition: WalkResult.h:47
bool wasInterrupted() const
Returns true if the walk was interrupted.
Definition: WalkResult.h:51
static WalkResult interrupt()
Definition: WalkResult.h:46
static DenseArrayAttrImpl get(MLIRContext *context, ArrayRef< int32_t > content)
Builder from ArrayRef<T>.
A named class for passing around the variadic flag.
Value createGlobalString(Location loc, OpBuilder &builder, StringRef name, StringRef value, Linkage linkage)
Create an LLVM global containing the string "value" at the module containing surrounding the insertio...
Operation * parentLLVMModule(Operation *op)
Lookup parent Module satisfying LLVM conditions on the Module Operation.
Type getVectorType(Type elementType, unsigned numElements, bool isScalable=false)
Creates an LLVM dialect-compatible vector type with the given element type and length.
Definition: LLVMTypes.cpp:840
bool isScalableVectorType(Type vectorType)
Returns whether a vector type is scalable or not.
Definition: LLVMTypes.cpp:834
bool isCompatibleVectorType(Type type)
Returns true if the given type is a vector type compatible with the LLVM dialect.
Definition: LLVMTypes.cpp:813
bool isCompatibleOuterType(Type type)
Returns true if the given outer type is compatible with the LLVM dialect without checking its potenti...
Definition: LLVMTypes.cpp:704
bool satisfiesLLVMModule(Operation *op)
LLVM requires some operations to be inside of a Module operation.
constexpr int kGEPConstantBitWidth
Bit-width of a 'GEPConstantIndex' within GEPArg.
Definition: LLVMDialect.h:62
bool isCompatibleType(Type type)
Returns true if the given type is compatible with the LLVM dialect.
Definition: LLVMTypes.cpp:795
bool isCompatibleFloatingPointType(Type type)
Returns true if the given type is a floating-point type compatible with the LLVM dialect.
Definition: LLVMTypes.cpp:808
llvm::ElementCount getVectorNumElements(Type type)
Returns the element count of any LLVM-compatible vector type.
Definition: LLVMTypes.cpp:826
void printFunctionSignature(OpAsmPrinter &p, TypeRange argTypes, ArrayAttr argAttrs, bool isVariadic, TypeRange resultTypes, ArrayAttr resultAttrs, Region *body=nullptr, bool printEmptyResult=true)
Print a function signature for a call or callable operation.
ParseResult parseFunctionSignature(OpAsmParser &parser, SmallVectorImpl< Type > &argTypes, SmallVectorImpl< DictionaryAttr > &argAttrs, SmallVectorImpl< Type > &resultTypes, SmallVectorImpl< DictionaryAttr > &resultAttrs, bool mustParseEmptyResult=true)
Parses a function signature using parser.
void addArgAndResultAttrs(Builder &builder, OperationState &result, ArrayRef< DictionaryAttr > argAttrs, ArrayRef< DictionaryAttr > resultAttrs, StringAttr argAttrsName, StringAttr resAttrsName)
Adds argument and result attributes, provided as argAttrs and resultAttrs arguments,...
void walk(Operation *op, function_ref< void(Region *)> callback, WalkOrder order)
Walk all of the regions, blocks, or operations nested under (and including) the given operation.
Definition: Visitors.h:102
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
Definition: Matchers.h:344
ParseResult parseFunctionSignatureWithArguments(OpAsmParser &parser, bool allowVariadic, SmallVectorImpl< OpAsmParser::Argument > &arguments, bool &isVariadic, SmallVectorImpl< Type > &resultTypes, SmallVectorImpl< DictionaryAttr > &resultAttrs)
Parses a function signature using parser.
void printFunctionAttributes(OpAsmPrinter &p, Operation *op, ArrayRef< StringRef > elided={})
Prints the list of function prefixed with the "attributes" keyword.
void printFunctionSignature(OpAsmPrinter &p, FunctionOpInterface op, ArrayRef< Type > argTypes, bool isVariadic, ArrayRef< Type > resultTypes)
Prints the signature of the function-like operation op.
Operation::operand_range getIndices(Operation *op)
Get the indices that the given load/store operation is operating on.
Definition: Utils.cpp:18
QueryRef parse(llvm::StringRef line, const QuerySession &qs)
Definition: Query.cpp:21
detail::InFlightRemark failed(Location loc, RemarkOpts opts)
Report an optimization remark that failed.
Definition: Remarks.h:491
Value constantIndex(OpBuilder &builder, Location loc, int64_t i)
Generates a constant of index type.
Definition: CodegenUtils.h:331
Visibility
This enum describes C++ inheritance visibility.
Definition: Class.h:426
std::string stringify(T &&t)
Generically convert a value to a std::string.
Include the generated interface declarations.
bool matchPattern(Value value, const Pattern &pattern)
Entry point for matching a pattern over a Value.
Definition: Matchers.h:490
detail::constant_int_value_binder m_ConstantInt(IntegerAttr::ValueType *bind_value)
Matches a constant holding a scalar/vector/tensor integer (splat) and writes the integer value to bin...
Definition: Matchers.h:527
const FrozenRewritePatternSet GreedyRewriteConfig bool * changed
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
Definition: Utils.cpp:304
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
detail::constant_op_matcher m_Constant()
Matches a constant foldable operation.
Definition: Matchers.h:369
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
Definition: Verifier.cpp:423
A callable is either a symbol, or an SSA value, that is referenced by a call-like operation.
This is the representation of an operand reference.
This represents an operation in an abstracted form, suitable for use with the builder APIs.
T & getOrAddProperties()
Get (or create) a properties of the provided type to be set on the operation on creation.
SmallVector< Value, 4 > operands
void addOperands(ValueRange newOperands)
void addAttributes(ArrayRef< NamedAttribute > newAttributes)
Add an array of named attributes.
void addAttribute(StringRef name, Attribute attr)
Add an attribute with the specified name.
void addSuccessors(Block *successor)
Adds a successor to the operation sate. successor must not be null.
void addTypes(ArrayRef< Type > newTypes)
NamedAttrList attributes
Region * addRegion()
Create a region that should be attached to the operation.