MLIR  20.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 
15 #include "LLVMInlining.h"
16 #include "TypeDetail.h"
20 #include "mlir/IR/Builders.h"
21 #include "mlir/IR/BuiltinOps.h"
22 #include "mlir/IR/BuiltinTypes.h"
24 #include "mlir/IR/MLIRContext.h"
25 #include "mlir/IR/Matchers.h"
27 
28 #include "llvm/ADT/SCCIterator.h"
29 #include "llvm/ADT/TypeSwitch.h"
30 #include "llvm/AsmParser/Parser.h"
31 #include "llvm/Bitcode/BitcodeReader.h"
32 #include "llvm/Bitcode/BitcodeWriter.h"
33 #include "llvm/IR/Attributes.h"
34 #include "llvm/IR/Function.h"
35 #include "llvm/IR/Type.h"
36 #include "llvm/Support/Error.h"
37 #include "llvm/Support/Mutex.h"
38 #include "llvm/Support/SourceMgr.h"
39 
40 #include <numeric>
41 #include <optional>
42 
43 using namespace mlir;
44 using namespace mlir::LLVM;
45 using mlir::LLVM::cconv::getMaxEnumValForCConv;
46 using mlir::LLVM::linkage::getMaxEnumValForLinkage;
47 using mlir::LLVM::tailcallkind::getMaxEnumValForTailCallKind;
48 
49 #include "mlir/Dialect/LLVMIR/LLVMOpsDialect.cpp.inc"
50 
51 //===----------------------------------------------------------------------===//
52 // Property Helpers
53 //===----------------------------------------------------------------------===//
54 
55 //===----------------------------------------------------------------------===//
56 // IntegerOverflowFlags
57 
58 namespace mlir {
60  IntegerOverflowFlags flags) {
61  return IntegerOverflowFlagsAttr::get(ctx, flags);
62 }
63 
64 static LogicalResult
65 convertFromAttribute(IntegerOverflowFlags &flags, Attribute attr,
67  auto flagsAttr = dyn_cast<IntegerOverflowFlagsAttr>(attr);
68  if (!flagsAttr) {
69  return emitError() << "expected 'overflowFlags' attribute to be an "
70  "IntegerOverflowFlagsAttr, but got "
71  << attr;
72  }
73  flags = flagsAttr.getValue();
74  return success();
75 }
76 } // namespace mlir
77 
78 static ParseResult parseOverflowFlags(AsmParser &p,
79  IntegerOverflowFlags &flags) {
80  if (failed(p.parseOptionalKeyword("overflow"))) {
81  flags = IntegerOverflowFlags::none;
82  return success();
83  }
84  if (p.parseLess())
85  return failure();
86  do {
87  StringRef kw;
88  SMLoc loc = p.getCurrentLocation();
89  if (p.parseKeyword(&kw))
90  return failure();
91  std::optional<IntegerOverflowFlags> flag =
92  symbolizeIntegerOverflowFlags(kw);
93  if (!flag)
94  return p.emitError(loc,
95  "invalid overflow flag: expected nsw, nuw, or none");
96  flags = flags | *flag;
97  } while (succeeded(p.parseOptionalComma()));
98  return p.parseGreater();
99 }
100 
102  IntegerOverflowFlags flags) {
103  if (flags == IntegerOverflowFlags::none)
104  return;
105  p << " overflow<";
107  if (bitEnumContainsAny(flags, IntegerOverflowFlags::nsw))
108  strs.push_back("nsw");
109  if (bitEnumContainsAny(flags, IntegerOverflowFlags::nuw))
110  strs.push_back("nuw");
111  llvm::interleaveComma(strs, p);
112  p << ">";
113 }
114 
115 //===----------------------------------------------------------------------===//
116 // Attribute Helpers
117 //===----------------------------------------------------------------------===//
118 
119 static constexpr const char kElemTypeAttrName[] = "elem_type";
120 
122  SmallVector<NamedAttribute, 8> filteredAttrs(
123  llvm::make_filter_range(attrs, [&](NamedAttribute attr) {
124  if (attr.getName() == "fastmathFlags") {
125  auto defAttr =
126  FastmathFlagsAttr::get(attr.getValue().getContext(), {});
127  return defAttr != attr.getValue();
128  }
129  return true;
130  }));
131  return filteredAttrs;
132 }
133 
134 static ParseResult parseLLVMOpAttrs(OpAsmParser &parser,
135  NamedAttrList &result) {
136  return parser.parseOptionalAttrDict(result);
137 }
138 
139 static void printLLVMOpAttrs(OpAsmPrinter &printer, Operation *op,
140  DictionaryAttr attrs) {
141  auto filteredAttrs = processFMFAttr(attrs.getValue());
142  if (auto iface = dyn_cast<IntegerOverflowFlagsInterface>(op)) {
143  printer.printOptionalAttrDict(
144  filteredAttrs, /*elidedAttrs=*/{iface.getOverflowFlagsAttrName()});
145  } else {
146  printer.printOptionalAttrDict(filteredAttrs);
147  }
148 }
149 
150 /// Verifies `symbol`'s use in `op` to ensure the symbol is a valid and
151 /// fully defined llvm.func.
152 static LogicalResult verifySymbolAttrUse(FlatSymbolRefAttr symbol,
153  Operation *op,
154  SymbolTableCollection &symbolTable) {
155  StringRef name = symbol.getValue();
156  auto func =
157  symbolTable.lookupNearestSymbolFrom<LLVMFuncOp>(op, symbol.getAttr());
158  if (!func)
159  return op->emitOpError("'")
160  << name << "' does not reference a valid LLVM function";
161  if (func.isExternal())
162  return op->emitOpError("'") << name << "' does not have a definition";
163  return success();
164 }
165 
166 /// Returns a boolean type that has the same shape as `type`. It supports both
167 /// fixed size vectors as well as scalable vectors.
168 static Type getI1SameShape(Type type) {
169  Type i1Type = IntegerType::get(type.getContext(), 1);
171  return LLVM::getVectorType(i1Type, LLVM::getVectorNumElements(type));
172  return i1Type;
173 }
174 
175 // Parses one of the keywords provided in the list `keywords` and returns the
176 // position of the parsed keyword in the list. If none of the keywords from the
177 // list is parsed, returns -1.
179  ArrayRef<StringRef> keywords) {
180  for (const auto &en : llvm::enumerate(keywords)) {
181  if (succeeded(parser.parseOptionalKeyword(en.value())))
182  return en.index();
183  }
184  return -1;
185 }
186 
187 namespace {
188 template <typename Ty>
189 struct EnumTraits {};
190 
191 #define REGISTER_ENUM_TYPE(Ty) \
192  template <> \
193  struct EnumTraits<Ty> { \
194  static StringRef stringify(Ty value) { return stringify##Ty(value); } \
195  static unsigned getMaxEnumVal() { return getMaxEnumValFor##Ty(); } \
196  }
197 
198 REGISTER_ENUM_TYPE(Linkage);
199 REGISTER_ENUM_TYPE(UnnamedAddr);
200 REGISTER_ENUM_TYPE(CConv);
201 REGISTER_ENUM_TYPE(TailCallKind);
203 } // namespace
204 
205 /// Parse an enum from the keyword, or default to the provided default value.
206 /// The return type is the enum type by default, unless overridden with the
207 /// second template argument.
208 template <typename EnumTy, typename RetTy = EnumTy>
210  OperationState &result,
211  EnumTy defaultValue) {
213  for (unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
214  names.push_back(EnumTraits<EnumTy>::stringify(static_cast<EnumTy>(i)));
215 
216  int index = parseOptionalKeywordAlternative(parser, names);
217  if (index == -1)
218  return static_cast<RetTy>(defaultValue);
219  return static_cast<RetTy>(index);
220 }
221 
222 //===----------------------------------------------------------------------===//
223 // Printing, parsing, folding and builder for LLVM::CmpOp.
224 //===----------------------------------------------------------------------===//
225 
226 void ICmpOp::print(OpAsmPrinter &p) {
227  p << " \"" << stringifyICmpPredicate(getPredicate()) << "\" " << getOperand(0)
228  << ", " << getOperand(1);
229  p.printOptionalAttrDict((*this)->getAttrs(), {"predicate"});
230  p << " : " << getLhs().getType();
231 }
232 
233 void FCmpOp::print(OpAsmPrinter &p) {
234  p << " \"" << stringifyFCmpPredicate(getPredicate()) << "\" " << getOperand(0)
235  << ", " << getOperand(1);
236  p.printOptionalAttrDict(processFMFAttr((*this)->getAttrs()), {"predicate"});
237  p << " : " << getLhs().getType();
238 }
239 
240 // <operation> ::= `llvm.icmp` string-literal ssa-use `,` ssa-use
241 // attribute-dict? `:` type
242 // <operation> ::= `llvm.fcmp` string-literal ssa-use `,` ssa-use
243 // attribute-dict? `:` type
244 template <typename CmpPredicateType>
245 static ParseResult parseCmpOp(OpAsmParser &parser, OperationState &result) {
246  StringAttr predicateAttr;
248  Type type;
249  SMLoc predicateLoc, trailingTypeLoc;
250  if (parser.getCurrentLocation(&predicateLoc) ||
251  parser.parseAttribute(predicateAttr, "predicate", result.attributes) ||
252  parser.parseOperand(lhs) || parser.parseComma() ||
253  parser.parseOperand(rhs) ||
254  parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
255  parser.getCurrentLocation(&trailingTypeLoc) || parser.parseType(type) ||
256  parser.resolveOperand(lhs, type, result.operands) ||
257  parser.resolveOperand(rhs, type, result.operands))
258  return failure();
259 
260  // Replace the string attribute `predicate` with an integer attribute.
261  int64_t predicateValue = 0;
262  if (std::is_same<CmpPredicateType, ICmpPredicate>()) {
263  std::optional<ICmpPredicate> predicate =
264  symbolizeICmpPredicate(predicateAttr.getValue());
265  if (!predicate)
266  return parser.emitError(predicateLoc)
267  << "'" << predicateAttr.getValue()
268  << "' is an incorrect value of the 'predicate' attribute";
269  predicateValue = static_cast<int64_t>(*predicate);
270  } else {
271  std::optional<FCmpPredicate> predicate =
272  symbolizeFCmpPredicate(predicateAttr.getValue());
273  if (!predicate)
274  return parser.emitError(predicateLoc)
275  << "'" << predicateAttr.getValue()
276  << "' is an incorrect value of the 'predicate' attribute";
277  predicateValue = static_cast<int64_t>(*predicate);
278  }
279 
280  result.attributes.set("predicate",
281  parser.getBuilder().getI64IntegerAttr(predicateValue));
282 
283  // The result type is either i1 or a vector type <? x i1> if the inputs are
284  // vectors.
285  if (!isCompatibleType(type))
286  return parser.emitError(trailingTypeLoc,
287  "expected LLVM dialect-compatible type");
288  result.addTypes(getI1SameShape(type));
289  return success();
290 }
291 
292 ParseResult ICmpOp::parse(OpAsmParser &parser, OperationState &result) {
293  return parseCmpOp<ICmpPredicate>(parser, result);
294 }
295 
296 ParseResult FCmpOp::parse(OpAsmParser &parser, OperationState &result) {
297  return parseCmpOp<FCmpPredicate>(parser, result);
298 }
299 
300 /// Returns a scalar or vector boolean attribute of the given type.
301 static Attribute getBoolAttribute(Type type, MLIRContext *ctx, bool value) {
302  auto boolAttr = BoolAttr::get(ctx, value);
303  ShapedType shapedType = dyn_cast<ShapedType>(type);
304  if (!shapedType)
305  return boolAttr;
306  return DenseElementsAttr::get(shapedType, boolAttr);
307 }
308 
309 OpFoldResult ICmpOp::fold(FoldAdaptor adaptor) {
310  if (getPredicate() != ICmpPredicate::eq &&
311  getPredicate() != ICmpPredicate::ne)
312  return {};
313 
314  // cmpi(eq/ne, x, x) -> true/false
315  if (getLhs() == getRhs())
316  return getBoolAttribute(getType(), getContext(),
317  getPredicate() == ICmpPredicate::eq);
318 
319  // cmpi(eq/ne, alloca, null) -> false/true
320  if (getLhs().getDefiningOp<AllocaOp>() && getRhs().getDefiningOp<ZeroOp>())
321  return getBoolAttribute(getType(), getContext(),
322  getPredicate() == ICmpPredicate::ne);
323 
324  // cmpi(eq/ne, null, alloca) -> cmpi(eq/ne, alloca, null)
325  if (getLhs().getDefiningOp<ZeroOp>() && getRhs().getDefiningOp<AllocaOp>()) {
326  Value lhs = getLhs();
327  Value rhs = getRhs();
328  getLhsMutable().assign(rhs);
329  getRhsMutable().assign(lhs);
330  return getResult();
331  }
332 
333  return {};
334 }
335 
336 //===----------------------------------------------------------------------===//
337 // Printing, parsing and verification for LLVM::AllocaOp.
338 //===----------------------------------------------------------------------===//
339 
340 void AllocaOp::print(OpAsmPrinter &p) {
341  auto funcTy =
342  FunctionType::get(getContext(), {getArraySize().getType()}, {getType()});
343 
344  if (getInalloca())
345  p << " inalloca";
346 
347  p << ' ' << getArraySize() << " x " << getElemType();
348  if (getAlignment() && *getAlignment() != 0)
349  p.printOptionalAttrDict((*this)->getAttrs(),
350  {kElemTypeAttrName, getInallocaAttrName()});
351  else
353  (*this)->getAttrs(),
354  {getAlignmentAttrName(), kElemTypeAttrName, getInallocaAttrName()});
355  p << " : " << funcTy;
356 }
357 
358 // <operation> ::= `llvm.alloca` `inalloca`? ssa-use `x` type
359 // attribute-dict? `:` type `,` type
360 ParseResult AllocaOp::parse(OpAsmParser &parser, OperationState &result) {
362  Type type, elemType;
363  SMLoc trailingTypeLoc;
364 
365  if (succeeded(parser.parseOptionalKeyword("inalloca")))
366  result.addAttribute(getInallocaAttrName(result.name),
367  UnitAttr::get(parser.getContext()));
368 
369  if (parser.parseOperand(arraySize) || parser.parseKeyword("x") ||
370  parser.parseType(elemType) ||
371  parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
372  parser.getCurrentLocation(&trailingTypeLoc) || parser.parseType(type))
373  return failure();
374 
375  std::optional<NamedAttribute> alignmentAttr =
376  result.attributes.getNamed("alignment");
377  if (alignmentAttr.has_value()) {
378  auto alignmentInt = llvm::dyn_cast<IntegerAttr>(alignmentAttr->getValue());
379  if (!alignmentInt)
380  return parser.emitError(parser.getNameLoc(),
381  "expected integer alignment");
382  if (alignmentInt.getValue().isZero())
383  result.attributes.erase("alignment");
384  }
385 
386  // Extract the result type from the trailing function type.
387  auto funcType = llvm::dyn_cast<FunctionType>(type);
388  if (!funcType || funcType.getNumInputs() != 1 ||
389  funcType.getNumResults() != 1)
390  return parser.emitError(
391  trailingTypeLoc,
392  "expected trailing function type with one argument and one result");
393 
394  if (parser.resolveOperand(arraySize, funcType.getInput(0), result.operands))
395  return failure();
396 
397  Type resultType = funcType.getResult(0);
398  if (auto ptrResultType = llvm::dyn_cast<LLVMPointerType>(resultType))
399  result.addAttribute(kElemTypeAttrName, TypeAttr::get(elemType));
400 
401  result.addTypes({funcType.getResult(0)});
402  return success();
403 }
404 
405 LogicalResult AllocaOp::verify() {
406  // Only certain target extension types can be used in 'alloca'.
407  if (auto targetExtType = dyn_cast<LLVMTargetExtType>(getElemType());
408  targetExtType && !targetExtType.supportsMemOps())
409  return emitOpError()
410  << "this target extension type cannot be used in alloca";
411 
412  return success();
413 }
414 
415 Type AllocaOp::getResultPtrElementType() { return getElemType(); }
416 
417 //===----------------------------------------------------------------------===//
418 // LLVM::BrOp
419 //===----------------------------------------------------------------------===//
420 
422  assert(index == 0 && "invalid successor index");
423  return SuccessorOperands(getDestOperandsMutable());
424 }
425 
426 //===----------------------------------------------------------------------===//
427 // LLVM::CondBrOp
428 //===----------------------------------------------------------------------===//
429 
431  assert(index < getNumSuccessors() && "invalid successor index");
432  return SuccessorOperands(index == 0 ? getTrueDestOperandsMutable()
433  : getFalseDestOperandsMutable());
434 }
435 
436 void CondBrOp::build(OpBuilder &builder, OperationState &result,
437  Value condition, Block *trueDest, ValueRange trueOperands,
438  Block *falseDest, ValueRange falseOperands,
439  std::optional<std::pair<uint32_t, uint32_t>> weights) {
440  DenseI32ArrayAttr weightsAttr;
441  if (weights)
442  weightsAttr =
443  builder.getDenseI32ArrayAttr({static_cast<int32_t>(weights->first),
444  static_cast<int32_t>(weights->second)});
445 
446  build(builder, result, condition, trueOperands, falseOperands, weightsAttr,
447  /*loop_annotation=*/{}, trueDest, falseDest);
448 }
449 
450 //===----------------------------------------------------------------------===//
451 // LLVM::SwitchOp
452 //===----------------------------------------------------------------------===//
453 
454 void SwitchOp::build(OpBuilder &builder, OperationState &result, Value value,
455  Block *defaultDestination, ValueRange defaultOperands,
456  DenseIntElementsAttr caseValues,
457  BlockRange caseDestinations,
458  ArrayRef<ValueRange> caseOperands,
459  ArrayRef<int32_t> branchWeights) {
460  DenseI32ArrayAttr weightsAttr;
461  if (!branchWeights.empty())
462  weightsAttr = builder.getDenseI32ArrayAttr(branchWeights);
463 
464  build(builder, result, value, defaultOperands, caseOperands, caseValues,
465  weightsAttr, defaultDestination, caseDestinations);
466 }
467 
468 void SwitchOp::build(OpBuilder &builder, OperationState &result, Value value,
469  Block *defaultDestination, ValueRange defaultOperands,
470  ArrayRef<APInt> caseValues, BlockRange caseDestinations,
471  ArrayRef<ValueRange> caseOperands,
472  ArrayRef<int32_t> branchWeights) {
473  DenseIntElementsAttr caseValuesAttr;
474  if (!caseValues.empty()) {
475  ShapedType caseValueType = VectorType::get(
476  static_cast<int64_t>(caseValues.size()), value.getType());
477  caseValuesAttr = DenseIntElementsAttr::get(caseValueType, caseValues);
478  }
479 
480  build(builder, result, value, defaultDestination, defaultOperands,
481  caseValuesAttr, caseDestinations, caseOperands, branchWeights);
482 }
483 
484 void SwitchOp::build(OpBuilder &builder, OperationState &result, Value value,
485  Block *defaultDestination, ValueRange defaultOperands,
486  ArrayRef<int32_t> caseValues, BlockRange caseDestinations,
487  ArrayRef<ValueRange> caseOperands,
488  ArrayRef<int32_t> branchWeights) {
489  DenseIntElementsAttr caseValuesAttr;
490  if (!caseValues.empty()) {
491  ShapedType caseValueType = VectorType::get(
492  static_cast<int64_t>(caseValues.size()), value.getType());
493  caseValuesAttr = DenseIntElementsAttr::get(caseValueType, caseValues);
494  }
495 
496  build(builder, result, value, defaultDestination, defaultOperands,
497  caseValuesAttr, caseDestinations, caseOperands, branchWeights);
498 }
499 
500 /// <cases> ::= `[` (case (`,` case )* )? `]`
501 /// <case> ::= integer `:` bb-id (`(` ssa-use-and-type-list `)`)?
502 static ParseResult parseSwitchOpCases(
503  OpAsmParser &parser, Type flagType, DenseIntElementsAttr &caseValues,
504  SmallVectorImpl<Block *> &caseDestinations,
506  SmallVectorImpl<SmallVector<Type>> &caseOperandTypes) {
507  if (failed(parser.parseLSquare()))
508  return failure();
509  if (succeeded(parser.parseOptionalRSquare()))
510  return success();
511  SmallVector<APInt> values;
512  unsigned bitWidth = flagType.getIntOrFloatBitWidth();
513  auto parseCase = [&]() {
514  int64_t value = 0;
515  if (failed(parser.parseInteger(value)))
516  return failure();
517  values.push_back(APInt(bitWidth, value));
518 
519  Block *destination;
521  SmallVector<Type> operandTypes;
522  if (parser.parseColon() || parser.parseSuccessor(destination))
523  return failure();
524  if (!parser.parseOptionalLParen()) {
525  if (parser.parseOperandList(operands, OpAsmParser::Delimiter::None,
526  /*allowResultNumber=*/false) ||
527  parser.parseColonTypeList(operandTypes) || parser.parseRParen())
528  return failure();
529  }
530  caseDestinations.push_back(destination);
531  caseOperands.emplace_back(operands);
532  caseOperandTypes.emplace_back(operandTypes);
533  return success();
534  };
535  if (failed(parser.parseCommaSeparatedList(parseCase)))
536  return failure();
537 
538  ShapedType caseValueType =
539  VectorType::get(static_cast<int64_t>(values.size()), flagType);
540  caseValues = DenseIntElementsAttr::get(caseValueType, values);
541  return parser.parseRSquare();
542 }
543 
544 static void printSwitchOpCases(OpAsmPrinter &p, SwitchOp op, Type flagType,
545  DenseIntElementsAttr caseValues,
546  SuccessorRange caseDestinations,
547  OperandRangeRange caseOperands,
548  const TypeRangeRange &caseOperandTypes) {
549  p << '[';
550  p.printNewline();
551  if (!caseValues) {
552  p << ']';
553  return;
554  }
555 
556  size_t index = 0;
557  llvm::interleave(
558  llvm::zip(caseValues, caseDestinations),
559  [&](auto i) {
560  p << " ";
561  p << std::get<0>(i).getLimitedValue();
562  p << ": ";
563  p.printSuccessorAndUseList(std::get<1>(i), caseOperands[index++]);
564  },
565  [&] {
566  p << ',';
567  p.printNewline();
568  });
569  p.printNewline();
570  p << ']';
571 }
572 
573 LogicalResult SwitchOp::verify() {
574  if ((!getCaseValues() && !getCaseDestinations().empty()) ||
575  (getCaseValues() &&
576  getCaseValues()->size() !=
577  static_cast<int64_t>(getCaseDestinations().size())))
578  return emitOpError("expects number of case values to match number of "
579  "case destinations");
580  if (getBranchWeights() && getBranchWeights()->size() != getNumSuccessors())
581  return emitError("expects number of branch weights to match number of "
582  "successors: ")
583  << getBranchWeights()->size() << " vs " << getNumSuccessors();
584  if (getCaseValues() &&
585  getValue().getType() != getCaseValues()->getElementType())
586  return emitError("expects case value type to match condition value type");
587  return success();
588 }
589 
591  assert(index < getNumSuccessors() && "invalid successor index");
592  return SuccessorOperands(index == 0 ? getDefaultOperandsMutable()
593  : getCaseOperandsMutable(index - 1));
594 }
595 
596 //===----------------------------------------------------------------------===//
597 // Code for LLVM::GEPOp.
598 //===----------------------------------------------------------------------===//
599 
600 constexpr int32_t GEPOp::kDynamicIndex;
601 
603  return GEPIndicesAdaptor<ValueRange>(getRawConstantIndicesAttr(),
604  getDynamicIndices());
605 }
606 
607 /// Returns the elemental type of any LLVM-compatible vector type or self.
609  if (auto vectorType = llvm::dyn_cast<VectorType>(type))
610  return vectorType.getElementType();
611  if (auto scalableVectorType = llvm::dyn_cast<LLVMScalableVectorType>(type))
612  return scalableVectorType.getElementType();
613  if (auto fixedVectorType = llvm::dyn_cast<LLVMFixedVectorType>(type))
614  return fixedVectorType.getElementType();
615  return type;
616 }
617 
618 /// Destructures the 'indices' parameter into 'rawConstantIndices' and
619 /// 'dynamicIndices', encoding the former in the process. In the process,
620 /// dynamic indices which are used to index into a structure type are converted
621 /// to constant indices when possible. To do this, the GEPs element type should
622 /// be passed as first parameter.
623 static void destructureIndices(Type currType, ArrayRef<GEPArg> indices,
624  SmallVectorImpl<int32_t> &rawConstantIndices,
625  SmallVectorImpl<Value> &dynamicIndices) {
626  for (const GEPArg &iter : indices) {
627  // If the thing we are currently indexing into is a struct we must turn
628  // any integer constants into constant indices. If this is not possible
629  // we don't do anything here. The verifier will catch it and emit a proper
630  // error. All other canonicalization is done in the fold method.
631  bool requiresConst = !rawConstantIndices.empty() &&
632  isa_and_nonnull<LLVMStructType>(currType);
633  if (Value val = llvm::dyn_cast_if_present<Value>(iter)) {
634  APInt intC;
635  if (requiresConst && matchPattern(val, m_ConstantInt(&intC)) &&
636  intC.isSignedIntN(kGEPConstantBitWidth)) {
637  rawConstantIndices.push_back(intC.getSExtValue());
638  } else {
639  rawConstantIndices.push_back(GEPOp::kDynamicIndex);
640  dynamicIndices.push_back(val);
641  }
642  } else {
643  rawConstantIndices.push_back(iter.get<GEPConstantIndex>());
644  }
645 
646  // Skip for very first iteration of this loop. First index does not index
647  // within the aggregates, but is just a pointer offset.
648  if (rawConstantIndices.size() == 1 || !currType)
649  continue;
650 
651  currType =
652  TypeSwitch<Type, Type>(currType)
653  .Case<VectorType, LLVMScalableVectorType, LLVMFixedVectorType,
654  LLVMArrayType>([](auto containerType) {
655  return containerType.getElementType();
656  })
657  .Case([&](LLVMStructType structType) -> Type {
658  int64_t memberIndex = rawConstantIndices.back();
659  if (memberIndex >= 0 && static_cast<size_t>(memberIndex) <
660  structType.getBody().size())
661  return structType.getBody()[memberIndex];
662  return nullptr;
663  })
664  .Default(Type(nullptr));
665  }
666 }
667 
668 void GEPOp::build(OpBuilder &builder, OperationState &result, Type resultType,
669  Type elementType, Value basePtr, ArrayRef<GEPArg> indices,
670  bool inbounds, ArrayRef<NamedAttribute> attributes) {
671  SmallVector<int32_t> rawConstantIndices;
672  SmallVector<Value> dynamicIndices;
673  destructureIndices(elementType, indices, rawConstantIndices, dynamicIndices);
674 
675  result.addTypes(resultType);
676  result.addAttributes(attributes);
677  result.addAttribute(getRawConstantIndicesAttrName(result.name),
678  builder.getDenseI32ArrayAttr(rawConstantIndices));
679  if (inbounds) {
680  result.addAttribute(getInboundsAttrName(result.name),
681  builder.getUnitAttr());
682  }
683  result.addAttribute(kElemTypeAttrName, TypeAttr::get(elementType));
684  result.addOperands(basePtr);
685  result.addOperands(dynamicIndices);
686 }
687 
688 void GEPOp::build(OpBuilder &builder, OperationState &result, Type resultType,
689  Type elementType, Value basePtr, ValueRange indices,
690  bool inbounds, ArrayRef<NamedAttribute> attributes) {
691  build(builder, result, resultType, elementType, basePtr,
692  SmallVector<GEPArg>(indices), inbounds, attributes);
693 }
694 
695 static ParseResult
698  DenseI32ArrayAttr &rawConstantIndices) {
699  SmallVector<int32_t> constantIndices;
700 
701  auto idxParser = [&]() -> ParseResult {
702  int32_t constantIndex;
703  OptionalParseResult parsedInteger =
705  if (parsedInteger.has_value()) {
706  if (failed(parsedInteger.value()))
707  return failure();
708  constantIndices.push_back(constantIndex);
709  return success();
710  }
711 
712  constantIndices.push_back(LLVM::GEPOp::kDynamicIndex);
713  return parser.parseOperand(indices.emplace_back());
714  };
715  if (parser.parseCommaSeparatedList(idxParser))
716  return failure();
717 
718  rawConstantIndices =
719  DenseI32ArrayAttr::get(parser.getContext(), constantIndices);
720  return success();
721 }
722 
723 static void printGEPIndices(OpAsmPrinter &printer, LLVM::GEPOp gepOp,
724  OperandRange indices,
725  DenseI32ArrayAttr rawConstantIndices) {
726  llvm::interleaveComma(
727  GEPIndicesAdaptor<OperandRange>(rawConstantIndices, indices), printer,
729  if (Value val = llvm::dyn_cast_if_present<Value>(cst))
730  printer.printOperand(val);
731  else
732  printer << cst.get<IntegerAttr>().getInt();
733  });
734 }
735 
736 /// For the given `indices`, check if they comply with `baseGEPType`,
737 /// especially check against LLVMStructTypes nested within.
738 static LogicalResult
739 verifyStructIndices(Type baseGEPType, unsigned indexPos,
741  function_ref<InFlightDiagnostic()> emitOpError) {
742  if (indexPos >= indices.size())
743  // Stop searching
744  return success();
745 
746  return TypeSwitch<Type, LogicalResult>(baseGEPType)
747  .Case<LLVMStructType>([&](LLVMStructType structType) -> LogicalResult {
748  if (!indices[indexPos].is<IntegerAttr>())
749  return emitOpError() << "expected index " << indexPos
750  << " indexing a struct to be constant";
751 
752  int32_t gepIndex = indices[indexPos].get<IntegerAttr>().getInt();
753  ArrayRef<Type> elementTypes = structType.getBody();
754  if (gepIndex < 0 ||
755  static_cast<size_t>(gepIndex) >= elementTypes.size())
756  return emitOpError() << "index " << indexPos
757  << " indexing a struct is out of bounds";
758 
759  // Instead of recursively going into every children types, we only
760  // dive into the one indexed by gepIndex.
761  return verifyStructIndices(elementTypes[gepIndex], indexPos + 1,
762  indices, emitOpError);
763  })
764  .Case<VectorType, LLVMScalableVectorType, LLVMFixedVectorType,
765  LLVMArrayType>([&](auto containerType) -> LogicalResult {
766  return verifyStructIndices(containerType.getElementType(), indexPos + 1,
767  indices, emitOpError);
768  })
769  .Default([&](auto otherType) -> LogicalResult {
770  return emitOpError()
771  << "type " << otherType << " cannot be indexed (index #"
772  << indexPos << ")";
773  });
774 }
775 
776 /// Driver function around `verifyStructIndices`.
777 static LogicalResult
779  function_ref<InFlightDiagnostic()> emitOpError) {
780  return verifyStructIndices(baseGEPType, /*indexPos=*/1, indices, emitOpError);
781 }
782 
783 LogicalResult LLVM::GEPOp::verify() {
784  if (static_cast<size_t>(
785  llvm::count(getRawConstantIndices(), kDynamicIndex)) !=
786  getDynamicIndices().size())
787  return emitOpError("expected as many dynamic indices as specified in '")
788  << getRawConstantIndicesAttrName().getValue() << "'";
789 
790  return verifyStructIndices(getElemType(), getIndices(),
791  [&] { return emitOpError(); });
792 }
793 
794 Type GEPOp::getResultPtrElementType() {
795  // Set the initial type currently being used for indexing. This will be
796  // updated as the indices get walked over.
797  Type selectedType = getElemType();
798 
799  // Follow the indexed elements in the gep.
800  auto indices = getIndices();
802  llvm::drop_begin(indices)) {
803  // GEPs can only index into aggregates which can be structs or arrays.
804 
805  // The resulting type if indexing into an array type is always the element
806  // type, regardless of index.
807  if (auto arrayType = dyn_cast<LLVMArrayType>(selectedType)) {
808  selectedType = arrayType.getElementType();
809  continue;
810  }
811 
812  // The GEP verifier ensures that any index into structs are static and
813  // that they refer to a field within the struct.
814  selectedType = cast<DestructurableTypeInterface>(selectedType)
815  .getTypeAtIndex(cast<IntegerAttr>(index));
816  }
817 
818  // When there are no more indices, the type currently being used for indexing
819  // is the type of the value pointed at by the returned indexed pointer.
820  return selectedType;
821 }
822 
823 //===----------------------------------------------------------------------===//
824 // LoadOp
825 //===----------------------------------------------------------------------===//
826 
827 void LoadOp::getEffects(
829  &effects) {
830  effects.emplace_back(MemoryEffects::Read::get(), &getAddrMutable());
831  // Volatile operations can have target-specific read-write effects on
832  // memory besides the one referred to by the pointer operand.
833  // Similarly, atomic operations that are monotonic or stricter cause
834  // synchronization that from a language point-of-view, are arbitrary
835  // read-writes into memory.
836  if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
837  getOrdering() != AtomicOrdering::unordered)) {
838  effects.emplace_back(MemoryEffects::Write::get());
839  effects.emplace_back(MemoryEffects::Read::get());
840  }
841 }
842 
843 /// Returns true if the given type is supported by atomic operations. All
844 /// integer, float, and pointer types with a power-of-two bitsize and a minimal
845 /// size of 8 bits are supported.
847  const DataLayout &dataLayout) {
848  if (!isa<IntegerType, LLVMPointerType>(type))
850  return false;
851 
852  llvm::TypeSize bitWidth = dataLayout.getTypeSizeInBits(type);
853  if (bitWidth.isScalable())
854  return false;
855  // Needs to be at least 8 bits and a power of two.
856  return bitWidth >= 8 && (bitWidth & (bitWidth - 1)) == 0;
857 }
858 
859 /// Verifies the attributes and the type of atomic memory access operations.
860 template <typename OpTy>
861 LogicalResult verifyAtomicMemOp(OpTy memOp, Type valueType,
862  ArrayRef<AtomicOrdering> unsupportedOrderings) {
863  if (memOp.getOrdering() != AtomicOrdering::not_atomic) {
864  DataLayout dataLayout = DataLayout::closest(memOp);
865  if (!isTypeCompatibleWithAtomicOp(valueType, dataLayout))
866  return memOp.emitOpError("unsupported type ")
867  << valueType << " for atomic access";
868  if (llvm::is_contained(unsupportedOrderings, memOp.getOrdering()))
869  return memOp.emitOpError("unsupported ordering '")
870  << stringifyAtomicOrdering(memOp.getOrdering()) << "'";
871  if (!memOp.getAlignment())
872  return memOp.emitOpError("expected alignment for atomic access");
873  return success();
874  }
875  if (memOp.getSyncscope())
876  return memOp.emitOpError(
877  "expected syncscope to be null for non-atomic access");
878  return success();
879 }
880 
881 LogicalResult LoadOp::verify() {
882  Type valueType = getResult().getType();
883  return verifyAtomicMemOp(*this, valueType,
884  {AtomicOrdering::release, AtomicOrdering::acq_rel});
885 }
886 
887 void LoadOp::build(OpBuilder &builder, OperationState &state, Type type,
888  Value addr, unsigned alignment, bool isVolatile,
889  bool isNonTemporal, bool isInvariant,
890  AtomicOrdering ordering, StringRef syncscope) {
891  build(builder, state, type, addr,
892  alignment ? builder.getI64IntegerAttr(alignment) : nullptr, isVolatile,
893  isNonTemporal, isInvariant, ordering,
894  syncscope.empty() ? nullptr : builder.getStringAttr(syncscope),
895  /*access_groups=*/nullptr,
896  /*alias_scopes=*/nullptr, /*noalias_scopes=*/nullptr,
897  /*tbaa=*/nullptr);
898 }
899 
900 //===----------------------------------------------------------------------===//
901 // StoreOp
902 //===----------------------------------------------------------------------===//
903 
904 void StoreOp::getEffects(
906  &effects) {
907  effects.emplace_back(MemoryEffects::Write::get(), &getAddrMutable());
908  // Volatile operations can have target-specific read-write effects on
909  // memory besides the one referred to by the pointer operand.
910  // Similarly, atomic operations that are monotonic or stricter cause
911  // synchronization that from a language point-of-view, are arbitrary
912  // read-writes into memory.
913  if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
914  getOrdering() != AtomicOrdering::unordered)) {
915  effects.emplace_back(MemoryEffects::Write::get());
916  effects.emplace_back(MemoryEffects::Read::get());
917  }
918 }
919 
920 LogicalResult StoreOp::verify() {
921  Type valueType = getValue().getType();
922  return verifyAtomicMemOp(*this, valueType,
923  {AtomicOrdering::acquire, AtomicOrdering::acq_rel});
924 }
925 
926 void StoreOp::build(OpBuilder &builder, OperationState &state, Value value,
927  Value addr, unsigned alignment, bool isVolatile,
928  bool isNonTemporal, AtomicOrdering ordering,
929  StringRef syncscope) {
930  build(builder, state, value, addr,
931  alignment ? builder.getI64IntegerAttr(alignment) : nullptr, isVolatile,
932  isNonTemporal, ordering,
933  syncscope.empty() ? nullptr : builder.getStringAttr(syncscope),
934  /*access_groups=*/nullptr,
935  /*alias_scopes=*/nullptr, /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr);
936 }
937 
938 //===----------------------------------------------------------------------===//
939 // CallOp
940 //===----------------------------------------------------------------------===//
941 
942 /// Gets the MLIR Op-like result types of a LLVMFunctionType.
943 static SmallVector<Type, 1> getCallOpResultTypes(LLVMFunctionType calleeType) {
944  SmallVector<Type, 1> results;
945  Type resultType = calleeType.getReturnType();
946  if (!isa<LLVM::LLVMVoidType>(resultType))
947  results.push_back(resultType);
948  return results;
949 }
950 
951 /// Gets the variadic callee type for a LLVMFunctionType.
952 static TypeAttr getCallOpVarCalleeType(LLVMFunctionType calleeType) {
953  return calleeType.isVarArg() ? TypeAttr::get(calleeType) : nullptr;
954 }
955 
956 /// Constructs a LLVMFunctionType from MLIR `results` and `args`.
957 static LLVMFunctionType getLLVMFuncType(MLIRContext *context, TypeRange results,
958  ValueRange args) {
959  Type resultType;
960  if (results.empty())
961  resultType = LLVMVoidType::get(context);
962  else
963  resultType = results.front();
964  return LLVMFunctionType::get(resultType, llvm::to_vector(args.getTypes()),
965  /*isVarArg=*/false);
966 }
967 
968 void CallOp::build(OpBuilder &builder, OperationState &state, TypeRange results,
969  StringRef callee, ValueRange args) {
970  build(builder, state, results, builder.getStringAttr(callee), args);
971 }
972 
973 void CallOp::build(OpBuilder &builder, OperationState &state, TypeRange results,
974  StringAttr callee, ValueRange args) {
975  build(builder, state, results, SymbolRefAttr::get(callee), args);
976 }
977 
978 void CallOp::build(OpBuilder &builder, OperationState &state, TypeRange results,
979  FlatSymbolRefAttr callee, ValueRange args) {
980  assert(callee && "expected non-null callee in direct call builder");
981  build(builder, state, results,
982  /*var_callee_type=*/nullptr, callee, args, /*fastmathFlags=*/nullptr,
983  /*branch_weights=*/nullptr,
984  /*CConv=*/nullptr, /*TailCallKind=*/nullptr,
985  /*memory_effects=*/nullptr,
986  /*convergent=*/nullptr, /*no_unwind=*/nullptr, /*will_return=*/nullptr,
987  /*access_groups=*/nullptr, /*alias_scopes=*/nullptr,
988  /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr);
989 }
990 
991 void CallOp::build(OpBuilder &builder, OperationState &state,
992  LLVMFunctionType calleeType, StringRef callee,
993  ValueRange args) {
994  build(builder, state, calleeType, builder.getStringAttr(callee), args);
995 }
996 
997 void CallOp::build(OpBuilder &builder, OperationState &state,
998  LLVMFunctionType calleeType, StringAttr callee,
999  ValueRange args) {
1000  build(builder, state, calleeType, SymbolRefAttr::get(callee), args);
1001 }
1002 
1003 void CallOp::build(OpBuilder &builder, OperationState &state,
1004  LLVMFunctionType calleeType, FlatSymbolRefAttr callee,
1005  ValueRange args) {
1006  build(builder, state, getCallOpResultTypes(calleeType),
1007  getCallOpVarCalleeType(calleeType), callee, args,
1008  /*fastmathFlags=*/nullptr,
1009  /*branch_weights=*/nullptr, /*CConv=*/nullptr,
1010  /*TailCallKind=*/nullptr, /*memory_effects=*/nullptr,
1011  /*convergent=*/nullptr,
1012  /*no_unwind=*/nullptr, /*will_return=*/nullptr,
1013  /*access_groups=*/nullptr,
1014  /*alias_scopes=*/nullptr, /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr);
1015 }
1016 
1017 void CallOp::build(OpBuilder &builder, OperationState &state,
1018  LLVMFunctionType calleeType, ValueRange args) {
1019  build(builder, state, getCallOpResultTypes(calleeType),
1020  getCallOpVarCalleeType(calleeType),
1021  /*callee=*/nullptr, args,
1022  /*fastmathFlags=*/nullptr, /*branch_weights=*/nullptr,
1023  /*CConv=*/nullptr, /*TailCallKind=*/nullptr, /*memory_effects=*/nullptr,
1024  /*convergent=*/nullptr, /*no_unwind=*/nullptr, /*will_return=*/nullptr,
1025  /*access_groups=*/nullptr, /*alias_scopes=*/nullptr,
1026  /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr);
1027 }
1028 
1029 void CallOp::build(OpBuilder &builder, OperationState &state, LLVMFuncOp func,
1030  ValueRange args) {
1031  auto calleeType = func.getFunctionType();
1032  build(builder, state, getCallOpResultTypes(calleeType),
1033  getCallOpVarCalleeType(calleeType), SymbolRefAttr::get(func), args,
1034  /*fastmathFlags=*/nullptr, /*branch_weights=*/nullptr,
1035  /*CConv=*/nullptr, /*TailCallKind=*/nullptr, /*memory_effects=*/nullptr,
1036  /*convergent=*/nullptr, /*no_unwind=*/nullptr, /*will_return=*/nullptr,
1037  /*access_groups=*/nullptr, /*alias_scopes=*/nullptr,
1038  /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr);
1039 }
1040 
1041 CallInterfaceCallable CallOp::getCallableForCallee() {
1042  // Direct call.
1043  if (FlatSymbolRefAttr calleeAttr = getCalleeAttr())
1044  return calleeAttr;
1045  // Indirect call, callee Value is the first operand.
1046  return getOperand(0);
1047 }
1048 
1049 void CallOp::setCalleeFromCallable(CallInterfaceCallable callee) {
1050  // Direct call.
1051  if (FlatSymbolRefAttr calleeAttr = getCalleeAttr()) {
1052  auto symRef = callee.get<SymbolRefAttr>();
1053  return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1054  }
1055  // Indirect call, callee Value is the first operand.
1056  return setOperand(0, callee.get<Value>());
1057 }
1058 
1059 Operation::operand_range CallOp::getArgOperands() {
1060  return getOperands().drop_front(getCallee().has_value() ? 0 : 1);
1061 }
1062 
1063 MutableOperandRange CallOp::getArgOperandsMutable() {
1064  return MutableOperandRange(*this, getCallee().has_value() ? 0 : 1,
1065  getCalleeOperands().size());
1066 }
1067 
1068 /// Verify that an inlinable callsite of a debug-info-bearing function in a
1069 /// debug-info-bearing function has a debug location attached to it. This
1070 /// mirrors an LLVM IR verifier.
1071 static LogicalResult verifyCallOpDebugInfo(CallOp callOp, LLVMFuncOp callee) {
1072  if (callee.isExternal())
1073  return success();
1074  auto parentFunc = callOp->getParentOfType<FunctionOpInterface>();
1075  if (!parentFunc)
1076  return success();
1077 
1078  auto hasSubprogram = [](Operation *op) {
1079  return op->getLoc()
1081  nullptr;
1082  };
1083  if (!hasSubprogram(parentFunc) || !hasSubprogram(callee))
1084  return success();
1085  bool containsLoc = !isa<UnknownLoc>(callOp->getLoc());
1086  if (!containsLoc)
1087  return callOp.emitError()
1088  << "inlinable function call in a function with a DISubprogram "
1089  "location must have a debug location";
1090  return success();
1091 }
1092 
1093 /// Verify that the parameter and return types of the variadic callee type match
1094 /// the `callOp` argument and result types.
1095 template <typename OpTy>
1096 LogicalResult verifyCallOpVarCalleeType(OpTy callOp) {
1097  std::optional<LLVMFunctionType> varCalleeType = callOp.getVarCalleeType();
1098  if (!varCalleeType)
1099  return success();
1100 
1101  // Verify the variadic callee type is a variadic function type.
1102  if (!varCalleeType->isVarArg())
1103  return callOp.emitOpError(
1104  "expected var_callee_type to be a variadic function type");
1105 
1106  // Verify the variadic callee type has at most as many parameters as the call
1107  // has argument operands.
1108  if (varCalleeType->getNumParams() > callOp.getArgOperands().size())
1109  return callOp.emitOpError("expected var_callee_type to have at most ")
1110  << callOp.getArgOperands().size() << " parameters";
1111 
1112  // Verify the variadic callee type matches the call argument types.
1113  for (auto [paramType, operand] :
1114  llvm::zip(varCalleeType->getParams(), callOp.getArgOperands()))
1115  if (paramType != operand.getType())
1116  return callOp.emitOpError()
1117  << "var_callee_type parameter type mismatch: " << paramType
1118  << " != " << operand.getType();
1119 
1120  // Verify the variadic callee type matches the call result type.
1121  if (!callOp.getNumResults()) {
1122  if (!isa<LLVMVoidType>(varCalleeType->getReturnType()))
1123  return callOp.emitOpError("expected var_callee_type to return void");
1124  } else {
1125  if (callOp.getResult().getType() != varCalleeType->getReturnType())
1126  return callOp.emitOpError("var_callee_type return type mismatch: ")
1127  << varCalleeType->getReturnType()
1128  << " != " << callOp.getResult().getType();
1129  }
1130  return success();
1131 }
1132 
1133 LogicalResult CallOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
1134  if (failed(verifyCallOpVarCalleeType(*this)))
1135  return failure();
1136 
1137  // Type for the callee, we'll get it differently depending if it is a direct
1138  // or indirect call.
1139  Type fnType;
1140 
1141  bool isIndirect = false;
1142 
1143  // If this is an indirect call, the callee attribute is missing.
1144  FlatSymbolRefAttr calleeName = getCalleeAttr();
1145  if (!calleeName) {
1146  isIndirect = true;
1147  if (!getNumOperands())
1148  return emitOpError(
1149  "must have either a `callee` attribute or at least an operand");
1150  auto ptrType = llvm::dyn_cast<LLVMPointerType>(getOperand(0).getType());
1151  if (!ptrType)
1152  return emitOpError("indirect call expects a pointer as callee: ")
1153  << getOperand(0).getType();
1154 
1155  return success();
1156  } else {
1157  Operation *callee =
1158  symbolTable.lookupNearestSymbolFrom(*this, calleeName.getAttr());
1159  if (!callee)
1160  return emitOpError()
1161  << "'" << calleeName.getValue()
1162  << "' does not reference a symbol in the current scope";
1163  auto fn = dyn_cast<LLVMFuncOp>(callee);
1164  if (!fn)
1165  return emitOpError() << "'" << calleeName.getValue()
1166  << "' does not reference a valid LLVM function";
1167 
1168  if (failed(verifyCallOpDebugInfo(*this, fn)))
1169  return failure();
1170  fnType = fn.getFunctionType();
1171  }
1172 
1173  LLVMFunctionType funcType = llvm::dyn_cast<LLVMFunctionType>(fnType);
1174  if (!funcType)
1175  return emitOpError("callee does not have a functional type: ") << fnType;
1176 
1177  if (funcType.isVarArg() && !getVarCalleeType())
1178  return emitOpError() << "missing var_callee_type attribute for vararg call";
1179 
1180  // Verify that the operand and result types match the callee.
1181 
1182  if (!funcType.isVarArg() &&
1183  funcType.getNumParams() != (getNumOperands() - isIndirect))
1184  return emitOpError() << "incorrect number of operands ("
1185  << (getNumOperands() - isIndirect)
1186  << ") for callee (expecting: "
1187  << funcType.getNumParams() << ")";
1188 
1189  if (funcType.getNumParams() > (getNumOperands() - isIndirect))
1190  return emitOpError() << "incorrect number of operands ("
1191  << (getNumOperands() - isIndirect)
1192  << ") for varargs callee (expecting at least: "
1193  << funcType.getNumParams() << ")";
1194 
1195  for (unsigned i = 0, e = funcType.getNumParams(); i != e; ++i)
1196  if (getOperand(i + isIndirect).getType() != funcType.getParamType(i))
1197  return emitOpError() << "operand type mismatch for operand " << i << ": "
1198  << getOperand(i + isIndirect).getType()
1199  << " != " << funcType.getParamType(i);
1200 
1201  if (getNumResults() == 0 &&
1202  !llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1203  return emitOpError() << "expected function call to produce a value";
1204 
1205  if (getNumResults() != 0 &&
1206  llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1207  return emitOpError()
1208  << "calling function with void result must not produce values";
1209 
1210  if (getNumResults() > 1)
1211  return emitOpError()
1212  << "expected LLVM function call to produce 0 or 1 result";
1213 
1214  if (getNumResults() && getResult().getType() != funcType.getReturnType())
1215  return emitOpError() << "result type mismatch: " << getResult().getType()
1216  << " != " << funcType.getReturnType();
1217 
1218  return success();
1219 }
1220 
1221 void CallOp::print(OpAsmPrinter &p) {
1222  auto callee = getCallee();
1223  bool isDirect = callee.has_value();
1224 
1225  p << ' ';
1226 
1227  // Print calling convention.
1228  if (getCConv() != LLVM::CConv::C)
1229  p << stringifyCConv(getCConv()) << ' ';
1230 
1231  if (getTailCallKind() != LLVM::TailCallKind::None)
1232  p << tailcallkind::stringifyTailCallKind(getTailCallKind()) << ' ';
1233 
1234  // Print the direct callee if present as a function attribute, or an indirect
1235  // callee (first operand) otherwise.
1236  if (isDirect)
1237  p.printSymbolName(callee.value());
1238  else
1239  p << getOperand(0);
1240 
1241  auto args = getOperands().drop_front(isDirect ? 0 : 1);
1242  p << '(' << args << ')';
1243 
1244  // Print the variadic callee type if the call is variadic.
1245  if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1246  p << " vararg(" << *varCalleeType << ")";
1247 
1248  p.printOptionalAttrDict(processFMFAttr((*this)->getAttrs()),
1249  {getCalleeAttrName(), getTailCallKindAttrName(),
1250  getVarCalleeTypeAttrName(), getCConvAttrName()});
1251 
1252  p << " : ";
1253  if (!isDirect)
1254  p << getOperand(0).getType() << ", ";
1255 
1256  // Reconstruct the function MLIR function type from operand and result types.
1257  p.printFunctionalType(args.getTypes(), getResultTypes());
1258 }
1259 
1260 /// Parses the type of a call operation and resolves the operands if the parsing
1261 /// succeeds. Returns failure otherwise.
1263  OpAsmParser &parser, OperationState &result, bool isDirect,
1265  SMLoc trailingTypesLoc = parser.getCurrentLocation();
1266  SmallVector<Type> types;
1267  if (parser.parseColonTypeList(types))
1268  return failure();
1269 
1270  if (isDirect && types.size() != 1)
1271  return parser.emitError(trailingTypesLoc,
1272  "expected direct call to have 1 trailing type");
1273  if (!isDirect && types.size() != 2)
1274  return parser.emitError(trailingTypesLoc,
1275  "expected indirect call to have 2 trailing types");
1276 
1277  auto funcType = llvm::dyn_cast<FunctionType>(types.pop_back_val());
1278  if (!funcType)
1279  return parser.emitError(trailingTypesLoc,
1280  "expected trailing function type");
1281  if (funcType.getNumResults() > 1)
1282  return parser.emitError(trailingTypesLoc,
1283  "expected function with 0 or 1 result");
1284  if (funcType.getNumResults() == 1 &&
1285  llvm::isa<LLVM::LLVMVoidType>(funcType.getResult(0)))
1286  return parser.emitError(trailingTypesLoc,
1287  "expected a non-void result type");
1288 
1289  // The head element of the types list matches the callee type for
1290  // indirect calls, while the types list is emtpy for direct calls.
1291  // Append the function input types to resolve the call operation
1292  // operands.
1293  llvm::append_range(types, funcType.getInputs());
1294  if (parser.resolveOperands(operands, types, parser.getNameLoc(),
1295  result.operands))
1296  return failure();
1297  if (funcType.getNumResults() != 0)
1298  result.addTypes(funcType.getResults());
1299 
1300  return success();
1301 }
1302 
1303 /// Parses an optional function pointer operand before the call argument list
1304 /// for indirect calls, or stops parsing at the function identifier otherwise.
1305 static ParseResult parseOptionalCallFuncPtr(
1306  OpAsmParser &parser,
1308  OpAsmParser::UnresolvedOperand funcPtrOperand;
1309  OptionalParseResult parseResult = parser.parseOptionalOperand(funcPtrOperand);
1310  if (parseResult.has_value()) {
1311  if (failed(*parseResult))
1312  return *parseResult;
1313  operands.push_back(funcPtrOperand);
1314  }
1315  return success();
1316 }
1317 
1318 // <operation> ::= `llvm.call` (cconv)? (tailcallkind)? (function-id | ssa-use)
1319 // `(` ssa-use-list `)`
1320 // ( `vararg(` var-callee-type `)` )?
1321 // attribute-dict? `:` (type `,`)? function-type
1322 ParseResult CallOp::parse(OpAsmParser &parser, OperationState &result) {
1323  SymbolRefAttr funcAttr;
1324  TypeAttr varCalleeType;
1326 
1327  // Default to C Calling Convention if no keyword is provided.
1328  result.addAttribute(
1329  getCConvAttrName(result.name),
1330  CConvAttr::get(parser.getContext(), parseOptionalLLVMKeyword<CConv>(
1331  parser, result, LLVM::CConv::C)));
1332 
1333  result.addAttribute(
1334  getTailCallKindAttrName(result.name),
1336  parseOptionalLLVMKeyword<TailCallKind>(
1337  parser, result, LLVM::TailCallKind::None)));
1338 
1339  // Parse a function pointer for indirect calls.
1340  if (parseOptionalCallFuncPtr(parser, operands))
1341  return failure();
1342  bool isDirect = operands.empty();
1343 
1344  // Parse a function identifier for direct calls.
1345  if (isDirect)
1346  if (parser.parseAttribute(funcAttr, "callee", result.attributes))
1347  return failure();
1348 
1349  // Parse the function arguments.
1350  if (parser.parseOperandList(operands, OpAsmParser::Delimiter::Paren))
1351  return failure();
1352 
1353  bool isVarArg = parser.parseOptionalKeyword("vararg").succeeded();
1354  if (isVarArg) {
1355  StringAttr varCalleeTypeAttrName =
1356  CallOp::getVarCalleeTypeAttrName(result.name);
1357  if (parser.parseLParen().failed() ||
1358  parser
1359  .parseAttribute(varCalleeType, varCalleeTypeAttrName,
1360  result.attributes)
1361  .failed() ||
1362  parser.parseRParen().failed())
1363  return failure();
1364  }
1365 
1366  if (parser.parseOptionalAttrDict(result.attributes))
1367  return failure();
1368 
1369  // Parse the trailing type list and resolve the operands.
1370  return parseCallTypeAndResolveOperands(parser, result, isDirect, operands);
1371 }
1372 
1373 LLVMFunctionType CallOp::getCalleeFunctionType() {
1374  if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1375  return *varCalleeType;
1376  return getLLVMFuncType(getContext(), getResultTypes(), getArgOperands());
1377 }
1378 
1379 ///===---------------------------------------------------------------------===//
1380 /// LLVM::InvokeOp
1381 ///===---------------------------------------------------------------------===//
1382 
1383 void InvokeOp::build(OpBuilder &builder, OperationState &state, LLVMFuncOp func,
1384  ValueRange ops, Block *normal, ValueRange normalOps,
1385  Block *unwind, ValueRange unwindOps) {
1386  auto calleeType = func.getFunctionType();
1387  build(builder, state, getCallOpResultTypes(calleeType),
1388  getCallOpVarCalleeType(calleeType), SymbolRefAttr::get(func), ops,
1389  normalOps, unwindOps, nullptr, nullptr, normal, unwind);
1390 }
1391 
1392 void InvokeOp::build(OpBuilder &builder, OperationState &state, TypeRange tys,
1393  FlatSymbolRefAttr callee, ValueRange ops, Block *normal,
1394  ValueRange normalOps, Block *unwind,
1395  ValueRange unwindOps) {
1396  build(builder, state, tys,
1397  /*var_callee_type=*/nullptr, callee, ops, normalOps, unwindOps, nullptr,
1398  nullptr, normal, unwind);
1399 }
1400 
1401 void InvokeOp::build(OpBuilder &builder, OperationState &state,
1402  LLVMFunctionType calleeType, FlatSymbolRefAttr callee,
1403  ValueRange ops, Block *normal, ValueRange normalOps,
1404  Block *unwind, ValueRange unwindOps) {
1405  build(builder, state, getCallOpResultTypes(calleeType),
1406  getCallOpVarCalleeType(calleeType), callee, ops, normalOps, unwindOps,
1407  nullptr, nullptr, normal, unwind);
1408 }
1409 
1411  assert(index < getNumSuccessors() && "invalid successor index");
1412  return SuccessorOperands(index == 0 ? getNormalDestOperandsMutable()
1413  : getUnwindDestOperandsMutable());
1414 }
1415 
1416 CallInterfaceCallable InvokeOp::getCallableForCallee() {
1417  // Direct call.
1418  if (FlatSymbolRefAttr calleeAttr = getCalleeAttr())
1419  return calleeAttr;
1420  // Indirect call, callee Value is the first operand.
1421  return getOperand(0);
1422 }
1423 
1424 void InvokeOp::setCalleeFromCallable(CallInterfaceCallable callee) {
1425  // Direct call.
1426  if (FlatSymbolRefAttr calleeAttr = getCalleeAttr()) {
1427  auto symRef = callee.get<SymbolRefAttr>();
1428  return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1429  }
1430  // Indirect call, callee Value is the first operand.
1431  return setOperand(0, callee.get<Value>());
1432 }
1433 
1434 Operation::operand_range InvokeOp::getArgOperands() {
1435  return getOperands().drop_front(getCallee().has_value() ? 0 : 1);
1436 }
1437 
1438 MutableOperandRange InvokeOp::getArgOperandsMutable() {
1439  return MutableOperandRange(*this, getCallee().has_value() ? 0 : 1,
1440  getCalleeOperands().size());
1441 }
1442 
1443 LogicalResult InvokeOp::verify() {
1444  if (failed(verifyCallOpVarCalleeType(*this)))
1445  return failure();
1446 
1447  Block *unwindDest = getUnwindDest();
1448  if (unwindDest->empty())
1449  return emitError("must have at least one operation in unwind destination");
1450 
1451  // In unwind destination, first operation must be LandingpadOp
1452  if (!isa<LandingpadOp>(unwindDest->front()))
1453  return emitError("first operation in unwind destination should be a "
1454  "llvm.landingpad operation");
1455 
1456  return success();
1457 }
1458 
1459 void InvokeOp::print(OpAsmPrinter &p) {
1460  auto callee = getCallee();
1461  bool isDirect = callee.has_value();
1462 
1463  p << ' ';
1464 
1465  // Print calling convention.
1466  if (getCConv() != LLVM::CConv::C)
1467  p << stringifyCConv(getCConv()) << ' ';
1468 
1469  // Either function name or pointer
1470  if (isDirect)
1471  p.printSymbolName(callee.value());
1472  else
1473  p << getOperand(0);
1474 
1475  p << '(' << getOperands().drop_front(isDirect ? 0 : 1) << ')';
1476  p << " to ";
1477  p.printSuccessorAndUseList(getNormalDest(), getNormalDestOperands());
1478  p << " unwind ";
1479  p.printSuccessorAndUseList(getUnwindDest(), getUnwindDestOperands());
1480 
1481  // Print the variadic callee type if the invoke is variadic.
1482  if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1483  p << " vararg(" << *varCalleeType << ")";
1484 
1485  p.printOptionalAttrDict((*this)->getAttrs(),
1486  {getCalleeAttrName(), getOperandSegmentSizeAttr(),
1487  getCConvAttrName(), getVarCalleeTypeAttrName()});
1488 
1489  p << " : ";
1490  if (!isDirect)
1491  p << getOperand(0).getType() << ", ";
1492  p.printFunctionalType(llvm::drop_begin(getOperandTypes(), isDirect ? 0 : 1),
1493  getResultTypes());
1494 }
1495 
1496 // <operation> ::= `llvm.invoke` (cconv)? (function-id | ssa-use)
1497 // `(` ssa-use-list `)`
1498 // `to` bb-id (`[` ssa-use-and-type-list `]`)?
1499 // `unwind` bb-id (`[` ssa-use-and-type-list `]`)?
1500 // ( `vararg(` var-callee-type `)` )?
1501 // attribute-dict? `:` (type `,`)? function-type
1502 ParseResult InvokeOp::parse(OpAsmParser &parser, OperationState &result) {
1504  SymbolRefAttr funcAttr;
1505  TypeAttr varCalleeType;
1506  Block *normalDest, *unwindDest;
1507  SmallVector<Value, 4> normalOperands, unwindOperands;
1508  Builder &builder = parser.getBuilder();
1509 
1510  // Default to C Calling Convention if no keyword is provided.
1511  result.addAttribute(
1512  getCConvAttrName(result.name),
1513  CConvAttr::get(parser.getContext(), parseOptionalLLVMKeyword<CConv>(
1514  parser, result, LLVM::CConv::C)));
1515 
1516  // Parse a function pointer for indirect calls.
1517  if (parseOptionalCallFuncPtr(parser, operands))
1518  return failure();
1519  bool isDirect = operands.empty();
1520 
1521  // Parse a function identifier for direct calls.
1522  if (isDirect && parser.parseAttribute(funcAttr, "callee", result.attributes))
1523  return failure();
1524 
1525  // Parse the function arguments.
1526  if (parser.parseOperandList(operands, OpAsmParser::Delimiter::Paren) ||
1527  parser.parseKeyword("to") ||
1528  parser.parseSuccessorAndUseList(normalDest, normalOperands) ||
1529  parser.parseKeyword("unwind") ||
1530  parser.parseSuccessorAndUseList(unwindDest, unwindOperands))
1531  return failure();
1532 
1533  bool isVarArg = parser.parseOptionalKeyword("vararg").succeeded();
1534  if (isVarArg) {
1535  StringAttr varCalleeTypeAttrName =
1536  InvokeOp::getVarCalleeTypeAttrName(result.name);
1537  if (parser.parseLParen().failed() ||
1538  parser
1539  .parseAttribute(varCalleeType, varCalleeTypeAttrName,
1540  result.attributes)
1541  .failed() ||
1542  parser.parseRParen().failed())
1543  return failure();
1544  }
1545 
1546  if (parser.parseOptionalAttrDict(result.attributes))
1547  return failure();
1548 
1549  // Parse the trailing type list and resolve the function operands.
1550  if (parseCallTypeAndResolveOperands(parser, result, isDirect, operands))
1551  return failure();
1552 
1553  result.addSuccessors({normalDest, unwindDest});
1554  result.addOperands(normalOperands);
1555  result.addOperands(unwindOperands);
1556 
1557  result.addAttribute(InvokeOp::getOperandSegmentSizeAttr(),
1558  builder.getDenseI32ArrayAttr(
1559  {static_cast<int32_t>(operands.size()),
1560  static_cast<int32_t>(normalOperands.size()),
1561  static_cast<int32_t>(unwindOperands.size())}));
1562  return success();
1563 }
1564 
1565 LLVMFunctionType InvokeOp::getCalleeFunctionType() {
1566  if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1567  return *varCalleeType;
1568  return getLLVMFuncType(getContext(), getResultTypes(), getArgOperands());
1569 }
1570 
1571 ///===----------------------------------------------------------------------===//
1572 /// Verifying/Printing/Parsing for LLVM::LandingpadOp.
1573 ///===----------------------------------------------------------------------===//
1574 
1575 LogicalResult LandingpadOp::verify() {
1576  Value value;
1577  if (LLVMFuncOp func = (*this)->getParentOfType<LLVMFuncOp>()) {
1578  if (!func.getPersonality())
1579  return emitError(
1580  "llvm.landingpad needs to be in a function with a personality");
1581  }
1582 
1583  // Consistency of llvm.landingpad result types is checked in
1584  // LLVMFuncOp::verify().
1585 
1586  if (!getCleanup() && getOperands().empty())
1587  return emitError("landingpad instruction expects at least one clause or "
1588  "cleanup attribute");
1589 
1590  for (unsigned idx = 0, ie = getNumOperands(); idx < ie; idx++) {
1591  value = getOperand(idx);
1592  bool isFilter = llvm::isa<LLVMArrayType>(value.getType());
1593  if (isFilter) {
1594  // FIXME: Verify filter clauses when arrays are appropriately handled
1595  } else {
1596  // catch - global addresses only.
1597  // Bitcast ops should have global addresses as their args.
1598  if (auto bcOp = value.getDefiningOp<BitcastOp>()) {
1599  if (auto addrOp = bcOp.getArg().getDefiningOp<AddressOfOp>())
1600  continue;
1601  return emitError("constant clauses expected").attachNote(bcOp.getLoc())
1602  << "global addresses expected as operand to "
1603  "bitcast used in clauses for landingpad";
1604  }
1605  // ZeroOp and AddressOfOp allowed
1606  if (value.getDefiningOp<ZeroOp>())
1607  continue;
1608  if (value.getDefiningOp<AddressOfOp>())
1609  continue;
1610  return emitError("clause #")
1611  << idx << " is not a known constant - null, addressof, bitcast";
1612  }
1613  }
1614  return success();
1615 }
1616 
1618  p << (getCleanup() ? " cleanup " : " ");
1619 
1620  // Clauses
1621  for (auto value : getOperands()) {
1622  // Similar to llvm - if clause is an array type then it is filter
1623  // clause else catch clause
1624  bool isArrayTy = llvm::isa<LLVMArrayType>(value.getType());
1625  p << '(' << (isArrayTy ? "filter " : "catch ") << value << " : "
1626  << value.getType() << ") ";
1627  }
1628 
1629  p.printOptionalAttrDict((*this)->getAttrs(), {"cleanup"});
1630 
1631  p << ": " << getType();
1632 }
1633 
1634 // <operation> ::= `llvm.landingpad` `cleanup`?
1635 // ((`catch` | `filter`) operand-type ssa-use)* attribute-dict?
1636 ParseResult LandingpadOp::parse(OpAsmParser &parser, OperationState &result) {
1637  // Check for cleanup
1638  if (succeeded(parser.parseOptionalKeyword("cleanup")))
1639  result.addAttribute("cleanup", parser.getBuilder().getUnitAttr());
1640 
1641  // Parse clauses with types
1642  while (succeeded(parser.parseOptionalLParen()) &&
1643  (succeeded(parser.parseOptionalKeyword("filter")) ||
1644  succeeded(parser.parseOptionalKeyword("catch")))) {
1646  Type ty;
1647  if (parser.parseOperand(operand) || parser.parseColon() ||
1648  parser.parseType(ty) ||
1649  parser.resolveOperand(operand, ty, result.operands) ||
1650  parser.parseRParen())
1651  return failure();
1652  }
1653 
1654  Type type;
1655  if (parser.parseColon() || parser.parseType(type))
1656  return failure();
1657 
1658  result.addTypes(type);
1659  return success();
1660 }
1661 
1662 //===----------------------------------------------------------------------===//
1663 // ExtractValueOp
1664 //===----------------------------------------------------------------------===//
1665 
1666 /// Extract the type at `position` in the LLVM IR aggregate type
1667 /// `containerType`. Each element of `position` is an index into a nested
1668 /// aggregate type. Return the resulting type or emit an error.
1670  function_ref<InFlightDiagnostic(StringRef)> emitError, Type containerType,
1671  ArrayRef<int64_t> position) {
1672  Type llvmType = containerType;
1673  if (!isCompatibleType(containerType)) {
1674  emitError("expected LLVM IR Dialect type, got ") << containerType;
1675  return {};
1676  }
1677 
1678  // Infer the element type from the structure type: iteratively step inside the
1679  // type by taking the element type, indexed by the position attribute for
1680  // structures. Check the position index before accessing, it is supposed to
1681  // be in bounds.
1682  for (int64_t idx : position) {
1683  if (auto arrayType = llvm::dyn_cast<LLVMArrayType>(llvmType)) {
1684  if (idx < 0 || static_cast<unsigned>(idx) >= arrayType.getNumElements()) {
1685  emitError("position out of bounds: ") << idx;
1686  return {};
1687  }
1688  llvmType = arrayType.getElementType();
1689  } else if (auto structType = llvm::dyn_cast<LLVMStructType>(llvmType)) {
1690  if (idx < 0 ||
1691  static_cast<unsigned>(idx) >= structType.getBody().size()) {
1692  emitError("position out of bounds: ") << idx;
1693  return {};
1694  }
1695  llvmType = structType.getBody()[idx];
1696  } else {
1697  emitError("expected LLVM IR structure/array type, got: ") << llvmType;
1698  return {};
1699  }
1700  }
1701  return llvmType;
1702 }
1703 
1704 /// Extract the type at `position` in the wrapped LLVM IR aggregate type
1705 /// `containerType`.
1707  ArrayRef<int64_t> position) {
1708  for (int64_t idx : position) {
1709  if (auto structType = llvm::dyn_cast<LLVMStructType>(llvmType))
1710  llvmType = structType.getBody()[idx];
1711  else
1712  llvmType = llvm::cast<LLVMArrayType>(llvmType).getElementType();
1713  }
1714  return llvmType;
1715 }
1716 
1717 OpFoldResult LLVM::ExtractValueOp::fold(FoldAdaptor adaptor) {
1718  auto insertValueOp = getContainer().getDefiningOp<InsertValueOp>();
1719  OpFoldResult result = {};
1720  while (insertValueOp) {
1721  if (getPosition() == insertValueOp.getPosition())
1722  return insertValueOp.getValue();
1723  unsigned min =
1724  std::min(getPosition().size(), insertValueOp.getPosition().size());
1725  // If one is fully prefix of the other, stop propagating back as it will
1726  // miss dependencies. For instance, %3 should not fold to %f0 in the
1727  // following example:
1728  // ```
1729  // %1 = llvm.insertvalue %f0, %0[0, 0] :
1730  // !llvm.array<4 x !llvm.array<4 x f32>>
1731  // %2 = llvm.insertvalue %arr, %1[0] :
1732  // !llvm.array<4 x !llvm.array<4 x f32>>
1733  // %3 = llvm.extractvalue %2[0, 0] : !llvm.array<4 x !llvm.array<4 x f32>>
1734  // ```
1735  if (getPosition().take_front(min) ==
1736  insertValueOp.getPosition().take_front(min))
1737  return result;
1738 
1739  // If neither a prefix, nor the exact position, we can extract out of the
1740  // value being inserted into. Moreover, we can try again if that operand
1741  // is itself an insertvalue expression.
1742  getContainerMutable().assign(insertValueOp.getContainer());
1743  result = getResult();
1744  insertValueOp = insertValueOp.getContainer().getDefiningOp<InsertValueOp>();
1745  }
1746  return result;
1747 }
1748 
1749 LogicalResult ExtractValueOp::verify() {
1750  auto emitError = [this](StringRef msg) { return emitOpError(msg); };
1752  emitError, getContainer().getType(), getPosition());
1753  if (!valueType)
1754  return failure();
1755 
1756  if (getRes().getType() != valueType)
1757  return emitOpError() << "Type mismatch: extracting from "
1758  << getContainer().getType() << " should produce "
1759  << valueType << " but this op returns "
1760  << getRes().getType();
1761  return success();
1762 }
1763 
1764 void ExtractValueOp::build(OpBuilder &builder, OperationState &state,
1765  Value container, ArrayRef<int64_t> position) {
1766  build(builder, state,
1767  getInsertExtractValueElementType(container.getType(), position),
1768  container, builder.getAttr<DenseI64ArrayAttr>(position));
1769 }
1770 
1771 //===----------------------------------------------------------------------===//
1772 // InsertValueOp
1773 //===----------------------------------------------------------------------===//
1774 
1775 /// Infer the value type from the container type and position.
1776 static ParseResult
1778  Type containerType,
1779  DenseI64ArrayAttr position) {
1781  [&](StringRef msg) {
1782  return parser.emitError(parser.getCurrentLocation(), msg);
1783  },
1784  containerType, position.asArrayRef());
1785  return success(!!valueType);
1786 }
1787 
1788 /// Nothing to print for an inferred type.
1790  Operation *op, Type valueType,
1791  Type containerType,
1792  DenseI64ArrayAttr position) {}
1793 
1794 LogicalResult InsertValueOp::verify() {
1795  auto emitError = [this](StringRef msg) { return emitOpError(msg); };
1797  emitError, getContainer().getType(), getPosition());
1798  if (!valueType)
1799  return failure();
1800 
1801  if (getValue().getType() != valueType)
1802  return emitOpError() << "Type mismatch: cannot insert "
1803  << getValue().getType() << " into "
1804  << getContainer().getType();
1805 
1806  return success();
1807 }
1808 
1809 //===----------------------------------------------------------------------===//
1810 // ReturnOp
1811 //===----------------------------------------------------------------------===//
1812 
1813 LogicalResult ReturnOp::verify() {
1814  auto parent = (*this)->getParentOfType<LLVMFuncOp>();
1815  if (!parent)
1816  return success();
1817 
1818  Type expectedType = parent.getFunctionType().getReturnType();
1819  if (llvm::isa<LLVMVoidType>(expectedType)) {
1820  if (!getArg())
1821  return success();
1822  InFlightDiagnostic diag = emitOpError("expected no operands");
1823  diag.attachNote(parent->getLoc()) << "when returning from function";
1824  return diag;
1825  }
1826  if (!getArg()) {
1827  if (llvm::isa<LLVMVoidType>(expectedType))
1828  return success();
1829  InFlightDiagnostic diag = emitOpError("expected 1 operand");
1830  diag.attachNote(parent->getLoc()) << "when returning from function";
1831  return diag;
1832  }
1833  if (expectedType != getArg().getType()) {
1834  InFlightDiagnostic diag = emitOpError("mismatching result types");
1835  diag.attachNote(parent->getLoc()) << "when returning from function";
1836  return diag;
1837  }
1838  return success();
1839 }
1840 
1841 //===----------------------------------------------------------------------===//
1842 // LLVM::AddressOfOp.
1843 //===----------------------------------------------------------------------===//
1844 
1846  Operation *module = op->getParentOp();
1847  while (module && !satisfiesLLVMModule(module))
1848  module = module->getParentOp();
1849  assert(module && "unexpected operation outside of a module");
1850  return module;
1851 }
1852 
1853 GlobalOp AddressOfOp::getGlobal(SymbolTableCollection &symbolTable) {
1854  return dyn_cast_or_null<GlobalOp>(
1855  symbolTable.lookupSymbolIn(parentLLVMModule(*this), getGlobalNameAttr()));
1856 }
1857 
1858 LLVMFuncOp AddressOfOp::getFunction(SymbolTableCollection &symbolTable) {
1859  return dyn_cast_or_null<LLVMFuncOp>(
1860  symbolTable.lookupSymbolIn(parentLLVMModule(*this), getGlobalNameAttr()));
1861 }
1862 
1863 LogicalResult
1864 AddressOfOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
1865  Operation *symbol =
1866  symbolTable.lookupSymbolIn(parentLLVMModule(*this), getGlobalNameAttr());
1867 
1868  auto global = dyn_cast_or_null<GlobalOp>(symbol);
1869  auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
1870 
1871  if (!global && !function)
1872  return emitOpError(
1873  "must reference a global defined by 'llvm.mlir.global' or 'llvm.func'");
1874 
1875  LLVMPointerType type = getType();
1876  if (global && global.getAddrSpace() != type.getAddressSpace())
1877  return emitOpError("pointer address space must match address space of the "
1878  "referenced global");
1879 
1880  return success();
1881 }
1882 
1883 // AddressOfOp constant-folds to the global symbol name.
1884 OpFoldResult LLVM::AddressOfOp::fold(FoldAdaptor) {
1885  return getGlobalNameAttr();
1886 }
1887 
1888 //===----------------------------------------------------------------------===//
1889 // Verifier for LLVM::ComdatOp.
1890 //===----------------------------------------------------------------------===//
1891 
1892 void ComdatOp::build(OpBuilder &builder, OperationState &result,
1893  StringRef symName) {
1894  result.addAttribute(getSymNameAttrName(result.name),
1895  builder.getStringAttr(symName));
1896  Region *body = result.addRegion();
1897  body->emplaceBlock();
1898 }
1899 
1900 LogicalResult ComdatOp::verifyRegions() {
1901  Region &body = getBody();
1902  for (Operation &op : body.getOps())
1903  if (!isa<ComdatSelectorOp>(op))
1904  return op.emitError(
1905  "only comdat selector symbols can appear in a comdat region");
1906 
1907  return success();
1908 }
1909 
1910 //===----------------------------------------------------------------------===//
1911 // Builder, printer and verifier for LLVM::GlobalOp.
1912 //===----------------------------------------------------------------------===//
1913 
1914 void GlobalOp::build(OpBuilder &builder, OperationState &result, Type type,
1915  bool isConstant, Linkage linkage, StringRef name,
1916  Attribute value, uint64_t alignment, unsigned addrSpace,
1917  bool dsoLocal, bool threadLocal, SymbolRefAttr comdat,
1919  DIGlobalVariableExpressionAttr dbgExpr) {
1920  result.addAttribute(getSymNameAttrName(result.name),
1921  builder.getStringAttr(name));
1922  result.addAttribute(getGlobalTypeAttrName(result.name), TypeAttr::get(type));
1923  if (isConstant)
1924  result.addAttribute(getConstantAttrName(result.name),
1925  builder.getUnitAttr());
1926  if (value)
1927  result.addAttribute(getValueAttrName(result.name), value);
1928  if (dsoLocal)
1929  result.addAttribute(getDsoLocalAttrName(result.name),
1930  builder.getUnitAttr());
1931  if (threadLocal)
1932  result.addAttribute(getThreadLocal_AttrName(result.name),
1933  builder.getUnitAttr());
1934  if (comdat)
1935  result.addAttribute(getComdatAttrName(result.name), comdat);
1936 
1937  // Only add an alignment attribute if the "alignment" input
1938  // is different from 0. The value must also be a power of two, but
1939  // this is tested in GlobalOp::verify, not here.
1940  if (alignment != 0)
1941  result.addAttribute(getAlignmentAttrName(result.name),
1942  builder.getI64IntegerAttr(alignment));
1943 
1944  result.addAttribute(getLinkageAttrName(result.name),
1945  LinkageAttr::get(builder.getContext(), linkage));
1946  if (addrSpace != 0)
1947  result.addAttribute(getAddrSpaceAttrName(result.name),
1948  builder.getI32IntegerAttr(addrSpace));
1949  result.attributes.append(attrs.begin(), attrs.end());
1950 
1951  if (dbgExpr)
1952  result.addAttribute(getDbgExprAttrName(result.name), dbgExpr);
1953 
1954  result.addRegion();
1955 }
1956 
1957 void GlobalOp::print(OpAsmPrinter &p) {
1958  p << ' ' << stringifyLinkage(getLinkage()) << ' ';
1959  StringRef visibility = stringifyVisibility(getVisibility_());
1960  if (!visibility.empty())
1961  p << visibility << ' ';
1962  if (getThreadLocal_())
1963  p << "thread_local ";
1964  if (auto unnamedAddr = getUnnamedAddr()) {
1965  StringRef str = stringifyUnnamedAddr(*unnamedAddr);
1966  if (!str.empty())
1967  p << str << ' ';
1968  }
1969  if (getConstant())
1970  p << "constant ";
1971  p.printSymbolName(getSymName());
1972  p << '(';
1973  if (auto value = getValueOrNull())
1974  p.printAttribute(value);
1975  p << ')';
1976  if (auto comdat = getComdat())
1977  p << " comdat(" << *comdat << ')';
1978 
1979  // Note that the alignment attribute is printed using the
1980  // default syntax here, even though it is an inherent attribute
1981  // (as defined in https://mlir.llvm.org/docs/LangRef/#attributes)
1982  p.printOptionalAttrDict((*this)->getAttrs(),
1983  {SymbolTable::getSymbolAttrName(),
1984  getGlobalTypeAttrName(), getConstantAttrName(),
1985  getValueAttrName(), getLinkageAttrName(),
1986  getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
1987  getVisibility_AttrName(), getComdatAttrName(),
1988  getUnnamedAddrAttrName()});
1989 
1990  // Print the trailing type unless it's a string global.
1991  if (llvm::dyn_cast_or_null<StringAttr>(getValueOrNull()))
1992  return;
1993  p << " : " << getType();
1994 
1995  Region &initializer = getInitializerRegion();
1996  if (!initializer.empty()) {
1997  p << ' ';
1998  p.printRegion(initializer, /*printEntryBlockArgs=*/false);
1999  }
2000 }
2001 
2002 static LogicalResult verifyComdat(Operation *op,
2003  std::optional<SymbolRefAttr> attr) {
2004  if (!attr)
2005  return success();
2006 
2007  auto *comdatSelector = SymbolTable::lookupNearestSymbolFrom(op, *attr);
2008  if (!isa_and_nonnull<ComdatSelectorOp>(comdatSelector))
2009  return op->emitError() << "expected comdat symbol";
2010 
2011  return success();
2012 }
2013 
2014 // operation ::= `llvm.mlir.global` linkage? visibility?
2015 // (`unnamed_addr` | `local_unnamed_addr`)?
2016 // `thread_local`? `constant`? `@` identifier
2017 // `(` attribute? `)` (`comdat(` symbol-ref-id `)`)?
2018 // attribute-list? (`:` type)? region?
2019 //
2020 // The type can be omitted for string attributes, in which case it will be
2021 // inferred from the value of the string as [strlen(value) x i8].
2022 ParseResult GlobalOp::parse(OpAsmParser &parser, OperationState &result) {
2023  MLIRContext *ctx = parser.getContext();
2024  // Parse optional linkage, default to External.
2025  result.addAttribute(getLinkageAttrName(result.name),
2027  ctx, parseOptionalLLVMKeyword<Linkage>(
2028  parser, result, LLVM::Linkage::External)));
2029 
2030  // Parse optional visibility, default to Default.
2031  result.addAttribute(getVisibility_AttrName(result.name),
2032  parser.getBuilder().getI64IntegerAttr(
2033  parseOptionalLLVMKeyword<LLVM::Visibility, int64_t>(
2034  parser, result, LLVM::Visibility::Default)));
2035 
2036  // Parse optional UnnamedAddr, default to None.
2037  result.addAttribute(getUnnamedAddrAttrName(result.name),
2038  parser.getBuilder().getI64IntegerAttr(
2039  parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
2040  parser, result, LLVM::UnnamedAddr::None)));
2041 
2042  if (succeeded(parser.parseOptionalKeyword("thread_local")))
2043  result.addAttribute(getThreadLocal_AttrName(result.name),
2044  parser.getBuilder().getUnitAttr());
2045 
2046  if (succeeded(parser.parseOptionalKeyword("constant")))
2047  result.addAttribute(getConstantAttrName(result.name),
2048  parser.getBuilder().getUnitAttr());
2049 
2050  StringAttr name;
2051  if (parser.parseSymbolName(name, getSymNameAttrName(result.name),
2052  result.attributes) ||
2053  parser.parseLParen())
2054  return failure();
2055 
2056  Attribute value;
2057  if (parser.parseOptionalRParen()) {
2058  if (parser.parseAttribute(value, getValueAttrName(result.name),
2059  result.attributes) ||
2060  parser.parseRParen())
2061  return failure();
2062  }
2063 
2064  if (succeeded(parser.parseOptionalKeyword("comdat"))) {
2065  SymbolRefAttr comdat;
2066  if (parser.parseLParen() || parser.parseAttribute(comdat) ||
2067  parser.parseRParen())
2068  return failure();
2069 
2070  result.addAttribute(getComdatAttrName(result.name), comdat);
2071  }
2072 
2073  SmallVector<Type, 1> types;
2074  if (parser.parseOptionalAttrDict(result.attributes) ||
2075  parser.parseOptionalColonTypeList(types))
2076  return failure();
2077 
2078  if (types.size() > 1)
2079  return parser.emitError(parser.getNameLoc(), "expected zero or one type");
2080 
2081  Region &initRegion = *result.addRegion();
2082  if (types.empty()) {
2083  if (auto strAttr = llvm::dyn_cast_or_null<StringAttr>(value)) {
2084  MLIRContext *context = parser.getContext();
2085  auto arrayType = LLVM::LLVMArrayType::get(IntegerType::get(context, 8),
2086  strAttr.getValue().size());
2087  types.push_back(arrayType);
2088  } else {
2089  return parser.emitError(parser.getNameLoc(),
2090  "type can only be omitted for string globals");
2091  }
2092  } else {
2093  OptionalParseResult parseResult =
2094  parser.parseOptionalRegion(initRegion, /*arguments=*/{},
2095  /*argTypes=*/{});
2096  if (parseResult.has_value() && failed(*parseResult))
2097  return failure();
2098  }
2099 
2100  result.addAttribute(getGlobalTypeAttrName(result.name),
2101  TypeAttr::get(types[0]));
2102  return success();
2103 }
2104 
2105 static bool isZeroAttribute(Attribute value) {
2106  if (auto intValue = llvm::dyn_cast<IntegerAttr>(value))
2107  return intValue.getValue().isZero();
2108  if (auto fpValue = llvm::dyn_cast<FloatAttr>(value))
2109  return fpValue.getValue().isZero();
2110  if (auto splatValue = llvm::dyn_cast<SplatElementsAttr>(value))
2111  return isZeroAttribute(splatValue.getSplatValue<Attribute>());
2112  if (auto elementsValue = llvm::dyn_cast<ElementsAttr>(value))
2113  return llvm::all_of(elementsValue.getValues<Attribute>(), isZeroAttribute);
2114  if (auto arrayValue = llvm::dyn_cast<ArrayAttr>(value))
2115  return llvm::all_of(arrayValue.getValue(), isZeroAttribute);
2116  return false;
2117 }
2118 
2119 LogicalResult GlobalOp::verify() {
2120  bool validType = isCompatibleOuterType(getType())
2121  ? !llvm::isa<LLVMVoidType, LLVMTokenType,
2122  LLVMMetadataType, LLVMLabelType>(getType())
2123  : llvm::isa<PointerElementTypeInterface>(getType());
2124  if (!validType)
2125  return emitOpError(
2126  "expects type to be a valid element type for an LLVM global");
2127  if ((*this)->getParentOp() && !satisfiesLLVMModule((*this)->getParentOp()))
2128  return emitOpError("must appear at the module level");
2129 
2130  if (auto strAttr = llvm::dyn_cast_or_null<StringAttr>(getValueOrNull())) {
2131  auto type = llvm::dyn_cast<LLVMArrayType>(getType());
2132  IntegerType elementType =
2133  type ? llvm::dyn_cast<IntegerType>(type.getElementType()) : nullptr;
2134  if (!elementType || elementType.getWidth() != 8 ||
2135  type.getNumElements() != strAttr.getValue().size())
2136  return emitOpError(
2137  "requires an i8 array type of the length equal to that of the string "
2138  "attribute");
2139  }
2140 
2141  if (auto targetExtType = dyn_cast<LLVMTargetExtType>(getType())) {
2142  if (!targetExtType.hasProperty(LLVMTargetExtType::CanBeGlobal))
2143  return emitOpError()
2144  << "this target extension type cannot be used in a global";
2145 
2146  if (Attribute value = getValueOrNull())
2147  return emitOpError() << "global with target extension type can only be "
2148  "initialized with zero-initializer";
2149  }
2150 
2151  if (getLinkage() == Linkage::Common) {
2152  if (Attribute value = getValueOrNull()) {
2153  if (!isZeroAttribute(value)) {
2154  return emitOpError()
2155  << "expected zero value for '"
2156  << stringifyLinkage(Linkage::Common) << "' linkage";
2157  }
2158  }
2159  }
2160 
2161  if (getLinkage() == Linkage::Appending) {
2162  if (!llvm::isa<LLVMArrayType>(getType())) {
2163  return emitOpError() << "expected array type for '"
2164  << stringifyLinkage(Linkage::Appending)
2165  << "' linkage";
2166  }
2167  }
2168 
2169  if (failed(verifyComdat(*this, getComdat())))
2170  return failure();
2171 
2172  std::optional<uint64_t> alignAttr = getAlignment();
2173  if (alignAttr.has_value()) {
2174  uint64_t value = alignAttr.value();
2175  if (!llvm::isPowerOf2_64(value))
2176  return emitError() << "alignment attribute is not a power of 2";
2177  }
2178 
2179  return success();
2180 }
2181 
2182 LogicalResult GlobalOp::verifyRegions() {
2183  if (Block *b = getInitializerBlock()) {
2184  ReturnOp ret = cast<ReturnOp>(b->getTerminator());
2185  if (ret.operand_type_begin() == ret.operand_type_end())
2186  return emitOpError("initializer region cannot return void");
2187  if (*ret.operand_type_begin() != getType())
2188  return emitOpError("initializer region type ")
2189  << *ret.operand_type_begin() << " does not match global type "
2190  << getType();
2191 
2192  for (Operation &op : *b) {
2193  auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2194  if (!iface || !iface.hasNoEffect())
2195  return op.emitError()
2196  << "ops with side effects not allowed in global initializers";
2197  }
2198 
2199  if (getValueOrNull())
2200  return emitOpError("cannot have both initializer value and region");
2201  }
2202 
2203  return success();
2204 }
2205 
2206 //===----------------------------------------------------------------------===//
2207 // LLVM::GlobalCtorsOp
2208 //===----------------------------------------------------------------------===//
2209 
2210 LogicalResult
2211 GlobalCtorsOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
2212  for (Attribute ctor : getCtors()) {
2213  if (failed(verifySymbolAttrUse(llvm::cast<FlatSymbolRefAttr>(ctor), *this,
2214  symbolTable)))
2215  return failure();
2216  }
2217  return success();
2218 }
2219 
2220 LogicalResult GlobalCtorsOp::verify() {
2221  if (getCtors().size() != getPriorities().size())
2222  return emitError(
2223  "mismatch between the number of ctors and the number of priorities");
2224  return success();
2225 }
2226 
2227 //===----------------------------------------------------------------------===//
2228 // LLVM::GlobalDtorsOp
2229 //===----------------------------------------------------------------------===//
2230 
2231 LogicalResult
2232 GlobalDtorsOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
2233  for (Attribute dtor : getDtors()) {
2234  if (failed(verifySymbolAttrUse(llvm::cast<FlatSymbolRefAttr>(dtor), *this,
2235  symbolTable)))
2236  return failure();
2237  }
2238  return success();
2239 }
2240 
2241 LogicalResult GlobalDtorsOp::verify() {
2242  if (getDtors().size() != getPriorities().size())
2243  return emitError(
2244  "mismatch between the number of dtors and the number of priorities");
2245  return success();
2246 }
2247 
2248 //===----------------------------------------------------------------------===//
2249 // ShuffleVectorOp
2250 //===----------------------------------------------------------------------===//
2251 
2252 void ShuffleVectorOp::build(OpBuilder &builder, OperationState &state, Value v1,
2253  Value v2, DenseI32ArrayAttr mask,
2254  ArrayRef<NamedAttribute> attrs) {
2255  auto containerType = v1.getType();
2256  auto vType = LLVM::getVectorType(LLVM::getVectorElementType(containerType),
2257  mask.size(),
2258  LLVM::isScalableVectorType(containerType));
2259  build(builder, state, vType, v1, v2, mask);
2260  state.addAttributes(attrs);
2261 }
2262 
2263 void ShuffleVectorOp::build(OpBuilder &builder, OperationState &state, Value v1,
2264  Value v2, ArrayRef<int32_t> mask) {
2265  build(builder, state, v1, v2, builder.getDenseI32ArrayAttr(mask));
2266 }
2267 
2268 /// Build the result type of a shuffle vector operation.
2269 static ParseResult parseShuffleType(AsmParser &parser, Type v1Type,
2270  Type &resType, DenseI32ArrayAttr mask) {
2271  if (!LLVM::isCompatibleVectorType(v1Type))
2272  return parser.emitError(parser.getCurrentLocation(),
2273  "expected an LLVM compatible vector type");
2274  resType = LLVM::getVectorType(LLVM::getVectorElementType(v1Type), mask.size(),
2275  LLVM::isScalableVectorType(v1Type));
2276  return success();
2277 }
2278 
2279 /// Nothing to do when the result type is inferred.
2280 static void printShuffleType(AsmPrinter &printer, Operation *op, Type v1Type,
2281  Type resType, DenseI32ArrayAttr mask) {}
2282 
2283 LogicalResult ShuffleVectorOp::verify() {
2284  if (LLVM::isScalableVectorType(getV1().getType()) &&
2285  llvm::any_of(getMask(), [](int32_t v) { return v != 0; }))
2286  return emitOpError("expected a splat operation for scalable vectors");
2287  return success();
2288 }
2289 
2290 //===----------------------------------------------------------------------===//
2291 // Implementations for LLVM::LLVMFuncOp.
2292 //===----------------------------------------------------------------------===//
2293 
2294 // Add the entry block to the function.
2295 Block *LLVMFuncOp::addEntryBlock(OpBuilder &builder) {
2296  assert(empty() && "function already has an entry block");
2297  OpBuilder::InsertionGuard g(builder);
2298  Block *entry = builder.createBlock(&getBody());
2299 
2300  // FIXME: Allow passing in proper locations for the entry arguments.
2301  LLVMFunctionType type = getFunctionType();
2302  for (unsigned i = 0, e = type.getNumParams(); i < e; ++i)
2303  entry->addArgument(type.getParamType(i), getLoc());
2304  return entry;
2305 }
2306 
2307 void LLVMFuncOp::build(OpBuilder &builder, OperationState &result,
2308  StringRef name, Type type, LLVM::Linkage linkage,
2309  bool dsoLocal, CConv cconv, SymbolRefAttr comdat,
2311  ArrayRef<DictionaryAttr> argAttrs,
2312  std::optional<uint64_t> functionEntryCount) {
2313  result.addRegion();
2315  builder.getStringAttr(name));
2316  result.addAttribute(getFunctionTypeAttrName(result.name),
2317  TypeAttr::get(type));
2318  result.addAttribute(getLinkageAttrName(result.name),
2319  LinkageAttr::get(builder.getContext(), linkage));
2320  result.addAttribute(getCConvAttrName(result.name),
2321  CConvAttr::get(builder.getContext(), cconv));
2322  result.attributes.append(attrs.begin(), attrs.end());
2323  if (dsoLocal)
2324  result.addAttribute(getDsoLocalAttrName(result.name),
2325  builder.getUnitAttr());
2326  if (comdat)
2327  result.addAttribute(getComdatAttrName(result.name), comdat);
2328  if (functionEntryCount)
2329  result.addAttribute(getFunctionEntryCountAttrName(result.name),
2330  builder.getI64IntegerAttr(functionEntryCount.value()));
2331  if (argAttrs.empty())
2332  return;
2333 
2334  assert(llvm::cast<LLVMFunctionType>(type).getNumParams() == argAttrs.size() &&
2335  "expected as many argument attribute lists as arguments");
2337  builder, result, argAttrs, /*resultAttrs=*/std::nullopt,
2338  getArgAttrsAttrName(result.name), getResAttrsAttrName(result.name));
2339 }
2340 
2341 // Builds an LLVM function type from the given lists of input and output types.
2342 // Returns a null type if any of the types provided are non-LLVM types, or if
2343 // there is more than one output type.
2344 static Type
2346  ArrayRef<Type> outputs,
2348  Builder &b = parser.getBuilder();
2349  if (outputs.size() > 1) {
2350  parser.emitError(loc, "failed to construct function type: expected zero or "
2351  "one function result");
2352  return {};
2353  }
2354 
2355  // Convert inputs to LLVM types, exit early on error.
2356  SmallVector<Type, 4> llvmInputs;
2357  for (auto t : inputs) {
2358  if (!isCompatibleType(t)) {
2359  parser.emitError(loc, "failed to construct function type: expected LLVM "
2360  "type for function arguments");
2361  return {};
2362  }
2363  llvmInputs.push_back(t);
2364  }
2365 
2366  // No output is denoted as "void" in LLVM type system.
2367  Type llvmOutput =
2368  outputs.empty() ? LLVMVoidType::get(b.getContext()) : outputs.front();
2369  if (!isCompatibleType(llvmOutput)) {
2370  parser.emitError(loc, "failed to construct function type: expected LLVM "
2371  "type for function results")
2372  << llvmOutput;
2373  return {};
2374  }
2375  return LLVMFunctionType::get(llvmOutput, llvmInputs,
2376  variadicFlag.isVariadic());
2377 }
2378 
2379 // Parses an LLVM function.
2380 //
2381 // operation ::= `llvm.func` linkage? cconv? function-signature
2382 // (`comdat(` symbol-ref-id `)`)?
2383 // function-attributes?
2384 // function-body
2385 //
2386 ParseResult LLVMFuncOp::parse(OpAsmParser &parser, OperationState &result) {
2387  // Default to external linkage if no keyword is provided.
2388  result.addAttribute(
2389  getLinkageAttrName(result.name),
2390  LinkageAttr::get(parser.getContext(),
2391  parseOptionalLLVMKeyword<Linkage>(
2392  parser, result, LLVM::Linkage::External)));
2393 
2394  // Parse optional visibility, default to Default.
2395  result.addAttribute(getVisibility_AttrName(result.name),
2396  parser.getBuilder().getI64IntegerAttr(
2397  parseOptionalLLVMKeyword<LLVM::Visibility, int64_t>(
2398  parser, result, LLVM::Visibility::Default)));
2399 
2400  // Parse optional UnnamedAddr, default to None.
2401  result.addAttribute(getUnnamedAddrAttrName(result.name),
2402  parser.getBuilder().getI64IntegerAttr(
2403  parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
2404  parser, result, LLVM::UnnamedAddr::None)));
2405 
2406  // Default to C Calling Convention if no keyword is provided.
2407  result.addAttribute(
2408  getCConvAttrName(result.name),
2409  CConvAttr::get(parser.getContext(), parseOptionalLLVMKeyword<CConv>(
2410  parser, result, LLVM::CConv::C)));
2411 
2412  StringAttr nameAttr;
2414  SmallVector<DictionaryAttr> resultAttrs;
2415  SmallVector<Type> resultTypes;
2416  bool isVariadic;
2417 
2418  auto signatureLocation = parser.getCurrentLocation();
2419  if (parser.parseSymbolName(nameAttr, SymbolTable::getSymbolAttrName(),
2420  result.attributes) ||
2422  parser, /*allowVariadic=*/true, entryArgs, isVariadic, resultTypes,
2423  resultAttrs))
2424  return failure();
2425 
2426  SmallVector<Type> argTypes;
2427  for (auto &arg : entryArgs)
2428  argTypes.push_back(arg.type);
2429  auto type =
2430  buildLLVMFunctionType(parser, signatureLocation, argTypes, resultTypes,
2432  if (!type)
2433  return failure();
2434  result.addAttribute(getFunctionTypeAttrName(result.name),
2435  TypeAttr::get(type));
2436 
2437  if (succeeded(parser.parseOptionalKeyword("vscale_range"))) {
2438  int64_t minRange, maxRange;
2439  if (parser.parseLParen() || parser.parseInteger(minRange) ||
2440  parser.parseComma() || parser.parseInteger(maxRange) ||
2441  parser.parseRParen())
2442  return failure();
2443  auto intTy = IntegerType::get(parser.getContext(), 32);
2444  result.addAttribute(
2445  getVscaleRangeAttrName(result.name),
2447  IntegerAttr::get(intTy, minRange),
2448  IntegerAttr::get(intTy, maxRange)));
2449  }
2450  // Parse the optional comdat selector.
2451  if (succeeded(parser.parseOptionalKeyword("comdat"))) {
2452  SymbolRefAttr comdat;
2453  if (parser.parseLParen() || parser.parseAttribute(comdat) ||
2454  parser.parseRParen())
2455  return failure();
2456 
2457  result.addAttribute(getComdatAttrName(result.name), comdat);
2458  }
2459 
2460  if (failed(parser.parseOptionalAttrDictWithKeyword(result.attributes)))
2461  return failure();
2463  parser.getBuilder(), result, entryArgs, resultAttrs,
2464  getArgAttrsAttrName(result.name), getResAttrsAttrName(result.name));
2465 
2466  auto *body = result.addRegion();
2467  OptionalParseResult parseResult =
2468  parser.parseOptionalRegion(*body, entryArgs);
2469  return failure(parseResult.has_value() && failed(*parseResult));
2470 }
2471 
2472 // Print the LLVMFuncOp. Collects argument and result types and passes them to
2473 // helper functions. Drops "void" result since it cannot be parsed back. Skips
2474 // the external linkage since it is the default value.
2476  p << ' ';
2477  if (getLinkage() != LLVM::Linkage::External)
2478  p << stringifyLinkage(getLinkage()) << ' ';
2479  StringRef visibility = stringifyVisibility(getVisibility_());
2480  if (!visibility.empty())
2481  p << visibility << ' ';
2482  if (auto unnamedAddr = getUnnamedAddr()) {
2483  StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2484  if (!str.empty())
2485  p << str << ' ';
2486  }
2487  if (getCConv() != LLVM::CConv::C)
2488  p << stringifyCConv(getCConv()) << ' ';
2489 
2490  p.printSymbolName(getName());
2491 
2492  LLVMFunctionType fnType = getFunctionType();
2493  SmallVector<Type, 8> argTypes;
2494  SmallVector<Type, 1> resTypes;
2495  argTypes.reserve(fnType.getNumParams());
2496  for (unsigned i = 0, e = fnType.getNumParams(); i < e; ++i)
2497  argTypes.push_back(fnType.getParamType(i));
2498 
2499  Type returnType = fnType.getReturnType();
2500  if (!llvm::isa<LLVMVoidType>(returnType))
2501  resTypes.push_back(returnType);
2502 
2504  isVarArg(), resTypes);
2505 
2506  // Print vscale range if present
2507  if (std::optional<VScaleRangeAttr> vscale = getVscaleRange())
2508  p << " vscale_range(" << vscale->getMinRange().getInt() << ", "
2509  << vscale->getMaxRange().getInt() << ')';
2510 
2511  // Print the optional comdat selector.
2512  if (auto comdat = getComdat())
2513  p << " comdat(" << *comdat << ')';
2514 
2516  p, *this,
2517  {getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
2518  getLinkageAttrName(), getCConvAttrName(), getVisibility_AttrName(),
2519  getComdatAttrName(), getUnnamedAddrAttrName(),
2520  getVscaleRangeAttrName()});
2521 
2522  // Print the body if this is not an external function.
2523  Region &body = getBody();
2524  if (!body.empty()) {
2525  p << ' ';
2526  p.printRegion(body, /*printEntryBlockArgs=*/false,
2527  /*printBlockTerminators=*/true);
2528  }
2529 }
2530 
2531 // Verifies LLVM- and implementation-specific properties of the LLVM func Op:
2532 // - functions don't have 'common' linkage
2533 // - external functions have 'external' or 'extern_weak' linkage;
2534 // - vararg is (currently) only supported for external functions;
2535 LogicalResult LLVMFuncOp::verify() {
2536  if (getLinkage() == LLVM::Linkage::Common)
2537  return emitOpError() << "functions cannot have '"
2538  << stringifyLinkage(LLVM::Linkage::Common)
2539  << "' linkage";
2540 
2541  if (failed(verifyComdat(*this, getComdat())))
2542  return failure();
2543 
2544  if (isExternal()) {
2545  if (getLinkage() != LLVM::Linkage::External &&
2546  getLinkage() != LLVM::Linkage::ExternWeak)
2547  return emitOpError() << "external functions must have '"
2548  << stringifyLinkage(LLVM::Linkage::External)
2549  << "' or '"
2550  << stringifyLinkage(LLVM::Linkage::ExternWeak)
2551  << "' linkage";
2552  return success();
2553  }
2554 
2555  // In LLVM IR, these attributes are composed by convention, not by design.
2556  if (isNoInline() && isAlwaysInline())
2557  return emitError("no_inline and always_inline attributes are incompatible");
2558 
2559  if (isOptimizeNone() && !isNoInline())
2560  return emitOpError("with optimize_none must also be no_inline");
2561 
2562  Type landingpadResultTy;
2563  StringRef diagnosticMessage;
2564  bool isLandingpadTypeConsistent =
2565  !walk([&](Operation *op) {
2566  const auto checkType = [&](Type type, StringRef errorMessage) {
2567  if (!landingpadResultTy) {
2568  landingpadResultTy = type;
2569  return WalkResult::advance();
2570  }
2571  if (landingpadResultTy != type) {
2572  diagnosticMessage = errorMessage;
2573  return WalkResult::interrupt();
2574  }
2575  return WalkResult::advance();
2576  };
2578  .Case<LandingpadOp>([&](auto landingpad) {
2579  constexpr StringLiteral errorMessage =
2580  "'llvm.landingpad' should have a consistent result type "
2581  "inside a function";
2582  return checkType(landingpad.getType(), errorMessage);
2583  })
2584  .Case<ResumeOp>([&](auto resume) {
2585  constexpr StringLiteral errorMessage =
2586  "'llvm.resume' should have a consistent input type inside a "
2587  "function";
2588  return checkType(resume.getValue().getType(), errorMessage);
2589  })
2590  .Default([](auto) { return WalkResult::skip(); });
2591  }).wasInterrupted();
2592  if (!isLandingpadTypeConsistent) {
2593  assert(!diagnosticMessage.empty() &&
2594  "Expecting a non-empty diagnostic message");
2595  return emitError(diagnosticMessage);
2596  }
2597 
2598  return success();
2599 }
2600 
2601 /// Verifies LLVM- and implementation-specific properties of the LLVM func Op:
2602 /// - entry block arguments are of LLVM types.
2603 LogicalResult LLVMFuncOp::verifyRegions() {
2604  if (isExternal())
2605  return success();
2606 
2607  unsigned numArguments = getFunctionType().getNumParams();
2608  Block &entryBlock = front();
2609  for (unsigned i = 0; i < numArguments; ++i) {
2610  Type argType = entryBlock.getArgument(i).getType();
2611  if (!isCompatibleType(argType))
2612  return emitOpError("entry block argument #")
2613  << i << " is not of LLVM type";
2614  }
2615 
2616  return success();
2617 }
2618 
2619 Region *LLVMFuncOp::getCallableRegion() {
2620  if (isExternal())
2621  return nullptr;
2622  return &getBody();
2623 }
2624 
2625 //===----------------------------------------------------------------------===//
2626 // UndefOp.
2627 //===----------------------------------------------------------------------===//
2628 
2629 /// Fold an undef operation to a dedicated undef attribute.
2630 OpFoldResult LLVM::UndefOp::fold(FoldAdaptor) {
2631  return LLVM::UndefAttr::get(getContext());
2632 }
2633 
2634 //===----------------------------------------------------------------------===//
2635 // PoisonOp.
2636 //===----------------------------------------------------------------------===//
2637 
2638 /// Fold a poison operation to a dedicated poison attribute.
2639 OpFoldResult LLVM::PoisonOp::fold(FoldAdaptor) {
2641 }
2642 
2643 //===----------------------------------------------------------------------===//
2644 // ZeroOp.
2645 //===----------------------------------------------------------------------===//
2646 
2647 LogicalResult LLVM::ZeroOp::verify() {
2648  if (auto targetExtType = dyn_cast<LLVMTargetExtType>(getType()))
2649  if (!targetExtType.hasProperty(LLVM::LLVMTargetExtType::HasZeroInit))
2650  return emitOpError()
2651  << "target extension type does not support zero-initializer";
2652 
2653  return success();
2654 }
2655 
2656 /// Fold a zero operation to a builtin zero attribute when possible and fall
2657 /// back to a dedicated zero attribute.
2658 OpFoldResult LLVM::ZeroOp::fold(FoldAdaptor) {
2660  if (result)
2661  return result;
2662  return LLVM::ZeroAttr::get(getContext());
2663 }
2664 
2665 //===----------------------------------------------------------------------===//
2666 // ConstantOp.
2667 //===----------------------------------------------------------------------===//
2668 
2669 LogicalResult LLVM::ConstantOp::verify() {
2670  if (StringAttr sAttr = llvm::dyn_cast<StringAttr>(getValue())) {
2671  auto arrayType = llvm::dyn_cast<LLVMArrayType>(getType());
2672  if (!arrayType || arrayType.getNumElements() != sAttr.getValue().size() ||
2673  !arrayType.getElementType().isInteger(8)) {
2674  return emitOpError() << "expected array type of "
2675  << sAttr.getValue().size()
2676  << " i8 elements for the string constant";
2677  }
2678  return success();
2679  }
2680  if (auto structType = llvm::dyn_cast<LLVMStructType>(getType())) {
2681  if (structType.getBody().size() != 2 ||
2682  structType.getBody()[0] != structType.getBody()[1]) {
2683  return emitError() << "expected struct type with two elements of the "
2684  "same type, the type of a complex constant";
2685  }
2686 
2687  auto arrayAttr = llvm::dyn_cast<ArrayAttr>(getValue());
2688  if (!arrayAttr || arrayAttr.size() != 2) {
2689  return emitOpError() << "expected array attribute with two elements, "
2690  "representing a complex constant";
2691  }
2692  auto re = llvm::dyn_cast<TypedAttr>(arrayAttr[0]);
2693  auto im = llvm::dyn_cast<TypedAttr>(arrayAttr[1]);
2694  if (!re || !im || re.getType() != im.getType()) {
2695  return emitOpError()
2696  << "expected array attribute with two elements of the same type";
2697  }
2698 
2699  Type elementType = structType.getBody()[0];
2700  if (!llvm::isa<IntegerType, Float16Type, Float32Type, Float64Type>(
2701  elementType)) {
2702  return emitError()
2703  << "expected struct element types to be floating point type or "
2704  "integer type";
2705  }
2706  return success();
2707  }
2708  if (auto targetExtType = dyn_cast<LLVMTargetExtType>(getType())) {
2709  return emitOpError() << "does not support target extension type.";
2710  }
2711  if (!llvm::isa<IntegerAttr, ArrayAttr, FloatAttr, ElementsAttr>(getValue()))
2712  return emitOpError()
2713  << "only supports integer, float, string or elements attributes";
2714  if (auto intAttr = dyn_cast<IntegerAttr>(getValue())) {
2715  if (!llvm::isa<IntegerType>(getType()))
2716  return emitOpError() << "expected integer type";
2717  }
2718  if (auto floatAttr = dyn_cast<FloatAttr>(getValue())) {
2719  const llvm::fltSemantics &sem = floatAttr.getValue().getSemantics();
2720  unsigned floatWidth = APFloat::getSizeInBits(sem);
2721  if (auto floatTy = dyn_cast<FloatType>(getType())) {
2722  if (floatTy.getWidth() != floatWidth) {
2723  return emitOpError() << "expected float type of width " << floatWidth;
2724  }
2725  }
2726  // See the comment for getLLVMConstant for more details about why 8-bit
2727  // floats can be represented by integers.
2728  if (isa<IntegerType>(getType()) && !getType().isInteger(floatWidth)) {
2729  return emitOpError() << "expected integer type of width " << floatWidth;
2730  }
2731  }
2732  if (auto splatAttr = dyn_cast<SplatElementsAttr>(getValue())) {
2733  if (!isa<VectorType>(getType()) && !isa<LLVM::LLVMArrayType>(getType()) &&
2734  !isa<LLVM::LLVMFixedVectorType>(getType()) &&
2735  !isa<LLVM::LLVMScalableVectorType>(getType()))
2736  return emitOpError() << "expected vector or array type";
2737  }
2738  return success();
2739 }
2740 
2741 bool LLVM::ConstantOp::isBuildableWith(Attribute value, Type type) {
2742  // The value's type must be the same as the provided type.
2743  auto typedAttr = dyn_cast<TypedAttr>(value);
2744  if (!typedAttr || typedAttr.getType() != type || !isCompatibleType(type))
2745  return false;
2746  // The value's type must be an LLVM compatible type.
2747  if (!isCompatibleType(type))
2748  return false;
2749  // TODO: Add support for additional attributes kinds once needed.
2750  return isa<IntegerAttr, FloatAttr, ElementsAttr>(value);
2751 }
2752 
2753 ConstantOp LLVM::ConstantOp::materialize(OpBuilder &builder, Attribute value,
2754  Type type, Location loc) {
2755  if (isBuildableWith(value, type))
2756  return builder.create<LLVM::ConstantOp>(loc, cast<TypedAttr>(value));
2757  return nullptr;
2758 }
2759 
2760 // Constant op constant-folds to its value.
2761 OpFoldResult LLVM::ConstantOp::fold(FoldAdaptor) { return getValue(); }
2762 
2763 //===----------------------------------------------------------------------===//
2764 // AtomicRMWOp
2765 //===----------------------------------------------------------------------===//
2766 
2767 void AtomicRMWOp::build(OpBuilder &builder, OperationState &state,
2768  AtomicBinOp binOp, Value ptr, Value val,
2769  AtomicOrdering ordering, StringRef syncscope,
2770  unsigned alignment, bool isVolatile) {
2771  build(builder, state, val.getType(), binOp, ptr, val, ordering,
2772  !syncscope.empty() ? builder.getStringAttr(syncscope) : nullptr,
2773  alignment ? builder.getI64IntegerAttr(alignment) : nullptr, isVolatile,
2774  /*access_groups=*/nullptr,
2775  /*alias_scopes=*/nullptr, /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr);
2776 }
2777 
2778 LogicalResult AtomicRMWOp::verify() {
2779  auto valType = getVal().getType();
2780  if (getBinOp() == AtomicBinOp::fadd || getBinOp() == AtomicBinOp::fsub ||
2781  getBinOp() == AtomicBinOp::fmin || getBinOp() == AtomicBinOp::fmax) {
2783  return emitOpError("expected LLVM IR floating point type");
2784  } else if (getBinOp() == AtomicBinOp::xchg) {
2785  DataLayout dataLayout = DataLayout::closest(*this);
2786  if (!isTypeCompatibleWithAtomicOp(valType, dataLayout))
2787  return emitOpError("unexpected LLVM IR type for 'xchg' bin_op");
2788  } else {
2789  auto intType = llvm::dyn_cast<IntegerType>(valType);
2790  unsigned intBitWidth = intType ? intType.getWidth() : 0;
2791  if (intBitWidth != 8 && intBitWidth != 16 && intBitWidth != 32 &&
2792  intBitWidth != 64)
2793  return emitOpError("expected LLVM IR integer type");
2794  }
2795 
2796  if (static_cast<unsigned>(getOrdering()) <
2797  static_cast<unsigned>(AtomicOrdering::monotonic))
2798  return emitOpError() << "expected at least '"
2799  << stringifyAtomicOrdering(AtomicOrdering::monotonic)
2800  << "' ordering";
2801 
2802  return success();
2803 }
2804 
2805 //===----------------------------------------------------------------------===//
2806 // AtomicCmpXchgOp
2807 //===----------------------------------------------------------------------===//
2808 
2809 /// Returns an LLVM struct type that contains a value type and a boolean type.
2811  auto boolType = IntegerType::get(valType.getContext(), 1);
2812  return LLVMStructType::getLiteral(valType.getContext(), {valType, boolType});
2813 }
2814 
2815 void AtomicCmpXchgOp::build(OpBuilder &builder, OperationState &state,
2816  Value ptr, Value cmp, Value val,
2817  AtomicOrdering successOrdering,
2818  AtomicOrdering failureOrdering, StringRef syncscope,
2819  unsigned alignment, bool isWeak, bool isVolatile) {
2820  build(builder, state, getValAndBoolStructType(val.getType()), ptr, cmp, val,
2821  successOrdering, failureOrdering,
2822  !syncscope.empty() ? builder.getStringAttr(syncscope) : nullptr,
2823  alignment ? builder.getI64IntegerAttr(alignment) : nullptr, isWeak,
2824  isVolatile, /*access_groups=*/nullptr,
2825  /*alias_scopes=*/nullptr, /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr);
2826 }
2827 
2828 LogicalResult AtomicCmpXchgOp::verify() {
2829  auto ptrType = llvm::cast<LLVM::LLVMPointerType>(getPtr().getType());
2830  if (!ptrType)
2831  return emitOpError("expected LLVM IR pointer type for operand #0");
2832  auto valType = getVal().getType();
2833  DataLayout dataLayout = DataLayout::closest(*this);
2834  if (!isTypeCompatibleWithAtomicOp(valType, dataLayout))
2835  return emitOpError("unexpected LLVM IR type");
2836  if (getSuccessOrdering() < AtomicOrdering::monotonic ||
2837  getFailureOrdering() < AtomicOrdering::monotonic)
2838  return emitOpError("ordering must be at least 'monotonic'");
2839  if (getFailureOrdering() == AtomicOrdering::release ||
2840  getFailureOrdering() == AtomicOrdering::acq_rel)
2841  return emitOpError("failure ordering cannot be 'release' or 'acq_rel'");
2842  return success();
2843 }
2844 
2845 //===----------------------------------------------------------------------===//
2846 // FenceOp
2847 //===----------------------------------------------------------------------===//
2848 
2849 void FenceOp::build(OpBuilder &builder, OperationState &state,
2850  AtomicOrdering ordering, StringRef syncscope) {
2851  build(builder, state, ordering,
2852  syncscope.empty() ? nullptr : builder.getStringAttr(syncscope));
2853 }
2854 
2855 LogicalResult FenceOp::verify() {
2856  if (getOrdering() == AtomicOrdering::not_atomic ||
2857  getOrdering() == AtomicOrdering::unordered ||
2858  getOrdering() == AtomicOrdering::monotonic)
2859  return emitOpError("can be given only acquire, release, acq_rel, "
2860  "and seq_cst orderings");
2861  return success();
2862 }
2863 
2864 //===----------------------------------------------------------------------===//
2865 // Verifier for extension ops
2866 //===----------------------------------------------------------------------===//
2867 
2868 /// Verifies that the given extension operation operates on consistent scalars
2869 /// or vectors, and that the target width is larger than the input width.
2870 template <class ExtOp>
2871 static LogicalResult verifyExtOp(ExtOp op) {
2872  IntegerType inputType, outputType;
2873  if (isCompatibleVectorType(op.getArg().getType())) {
2875  return op.emitError(
2876  "input type is a vector but output type is an integer");
2877  if (getVectorNumElements(op.getArg().getType()) !=
2879  return op.emitError("input and output vectors are of incompatible shape");
2880  // Because this is a CastOp, the element of vectors is guaranteed to be an
2881  // integer.
2882  inputType = cast<IntegerType>(getVectorElementType(op.getArg().getType()));
2883  outputType =
2884  cast<IntegerType>(getVectorElementType(op.getResult().getType()));
2885  } else {
2886  // Because this is a CastOp and arg is not a vector, arg is guaranteed to be
2887  // an integer.
2888  inputType = cast<IntegerType>(op.getArg().getType());
2889  outputType = dyn_cast<IntegerType>(op.getResult().getType());
2890  if (!outputType)
2891  return op.emitError(
2892  "input type is an integer but output type is a vector");
2893  }
2894 
2895  if (outputType.getWidth() <= inputType.getWidth())
2896  return op.emitError("integer width of the output type is smaller or "
2897  "equal to the integer width of the input type");
2898  return success();
2899 }
2900 
2901 //===----------------------------------------------------------------------===//
2902 // ZExtOp
2903 //===----------------------------------------------------------------------===//
2904 
2905 LogicalResult ZExtOp::verify() { return verifyExtOp<ZExtOp>(*this); }
2906 
2907 OpFoldResult LLVM::ZExtOp::fold(FoldAdaptor adaptor) {
2908  auto arg = dyn_cast_or_null<IntegerAttr>(adaptor.getArg());
2909  if (!arg)
2910  return {};
2911 
2912  size_t targetSize = cast<IntegerType>(getType()).getWidth();
2913  return IntegerAttr::get(getType(), arg.getValue().zext(targetSize));
2914 }
2915 
2916 //===----------------------------------------------------------------------===//
2917 // SExtOp
2918 //===----------------------------------------------------------------------===//
2919 
2920 LogicalResult SExtOp::verify() { return verifyExtOp<SExtOp>(*this); }
2921 
2922 //===----------------------------------------------------------------------===//
2923 // Folder and verifier for LLVM::BitcastOp
2924 //===----------------------------------------------------------------------===//
2925 
2926 /// Folds a cast op that can be chained.
2927 template <typename T>
2929  typename T::FoldAdaptor adaptor) {
2930  // cast(x : T0, T0) -> x
2931  if (castOp.getArg().getType() == castOp.getType())
2932  return castOp.getArg();
2933  if (auto prev = castOp.getArg().template getDefiningOp<T>()) {
2934  // cast(cast(x : T0, T1), T0) -> x
2935  if (prev.getArg().getType() == castOp.getType())
2936  return prev.getArg();
2937  // cast(cast(x : T0, T1), T2) -> cast(x: T0, T2)
2938  castOp.getArgMutable().set(prev.getArg());
2939  return Value{castOp};
2940  }
2941  return {};
2942 }
2943 
2944 OpFoldResult LLVM::BitcastOp::fold(FoldAdaptor adaptor) {
2945  return foldChainableCast(*this, adaptor);
2946 }
2947 
2948 LogicalResult LLVM::BitcastOp::verify() {
2949  auto resultType = llvm::dyn_cast<LLVMPointerType>(
2950  extractVectorElementType(getResult().getType()));
2951  auto sourceType = llvm::dyn_cast<LLVMPointerType>(
2952  extractVectorElementType(getArg().getType()));
2953 
2954  // If one of the types is a pointer (or vector of pointers), then
2955  // both source and result type have to be pointers.
2956  if (static_cast<bool>(resultType) != static_cast<bool>(sourceType))
2957  return emitOpError("can only cast pointers from and to pointers");
2958 
2959  if (!resultType)
2960  return success();
2961 
2962  auto isVector =
2963  llvm::IsaPred<VectorType, LLVMScalableVectorType, LLVMFixedVectorType>;
2964 
2965  // Due to bitcast requiring both operands to be of the same size, it is not
2966  // possible for only one of the two to be a pointer of vectors.
2967  if (isVector(getResult().getType()) && !isVector(getArg().getType()))
2968  return emitOpError("cannot cast pointer to vector of pointers");
2969 
2970  if (!isVector(getResult().getType()) && isVector(getArg().getType()))
2971  return emitOpError("cannot cast vector of pointers to pointer");
2972 
2973  // Bitcast cannot cast between pointers of different address spaces.
2974  // 'llvm.addrspacecast' must be used for this purpose instead.
2975  if (resultType.getAddressSpace() != sourceType.getAddressSpace())
2976  return emitOpError("cannot cast pointers of different address spaces, "
2977  "use 'llvm.addrspacecast' instead");
2978 
2979  return success();
2980 }
2981 
2982 //===----------------------------------------------------------------------===//
2983 // Folder for LLVM::AddrSpaceCastOp
2984 //===----------------------------------------------------------------------===//
2985 
2986 OpFoldResult LLVM::AddrSpaceCastOp::fold(FoldAdaptor adaptor) {
2987  return foldChainableCast(*this, adaptor);
2988 }
2989 
2990 //===----------------------------------------------------------------------===//
2991 // Folder for LLVM::GEPOp
2992 //===----------------------------------------------------------------------===//
2993 
2994 OpFoldResult LLVM::GEPOp::fold(FoldAdaptor adaptor) {
2995  GEPIndicesAdaptor<ArrayRef<Attribute>> indices(getRawConstantIndicesAttr(),
2996  adaptor.getDynamicIndices());
2997 
2998  // gep %x:T, 0 -> %x
2999  if (getBase().getType() == getType() && indices.size() == 1)
3000  if (auto integer = llvm::dyn_cast_or_null<IntegerAttr>(indices[0]))
3001  if (integer.getValue().isZero())
3002  return getBase();
3003 
3004  // Canonicalize any dynamic indices of constant value to constant indices.
3005  bool changed = false;
3006  SmallVector<GEPArg> gepArgs;
3007  for (auto iter : llvm::enumerate(indices)) {
3008  auto integer = llvm::dyn_cast_or_null<IntegerAttr>(iter.value());
3009  // Constant indices can only be int32_t, so if integer does not fit we
3010  // are forced to keep it dynamic, despite being a constant.
3011  if (!indices.isDynamicIndex(iter.index()) || !integer ||
3012  !integer.getValue().isSignedIntN(kGEPConstantBitWidth)) {
3013 
3014  PointerUnion<IntegerAttr, Value> existing = getIndices()[iter.index()];
3015  if (Value val = llvm::dyn_cast_if_present<Value>(existing))
3016  gepArgs.emplace_back(val);
3017  else
3018  gepArgs.emplace_back(existing.get<IntegerAttr>().getInt());
3019 
3020  continue;
3021  }
3022 
3023  changed = true;
3024  gepArgs.emplace_back(integer.getInt());
3025  }
3026  if (changed) {
3027  SmallVector<int32_t> rawConstantIndices;
3028  SmallVector<Value> dynamicIndices;
3029  destructureIndices(getElemType(), gepArgs, rawConstantIndices,
3030  dynamicIndices);
3031 
3032  getDynamicIndicesMutable().assign(dynamicIndices);
3033  setRawConstantIndices(rawConstantIndices);
3034  return Value{*this};
3035  }
3036 
3037  return {};
3038 }
3039 
3040 //===----------------------------------------------------------------------===//
3041 // ShlOp
3042 //===----------------------------------------------------------------------===//
3043 
3044 OpFoldResult LLVM::ShlOp::fold(FoldAdaptor adaptor) {
3045  auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3046  if (!rhs)
3047  return {};
3048 
3049  if (rhs.getValue().getZExtValue() >=
3050  getLhs().getType().getIntOrFloatBitWidth())
3051  return {}; // TODO: Fold into poison.
3052 
3053  auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3054  if (!lhs)
3055  return {};
3056 
3057  return IntegerAttr::get(getType(), lhs.getValue().shl(rhs.getValue()));
3058 }
3059 
3060 //===----------------------------------------------------------------------===//
3061 // OrOp
3062 //===----------------------------------------------------------------------===//
3063 
3064 OpFoldResult LLVM::OrOp::fold(FoldAdaptor adaptor) {
3065  auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3066  if (!lhs)
3067  return {};
3068 
3069  auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3070  if (!rhs)
3071  return {};
3072 
3073  return IntegerAttr::get(getType(), lhs.getValue() | rhs.getValue());
3074 }
3075 
3076 //===----------------------------------------------------------------------===//
3077 // CallIntrinsicOp
3078 //===----------------------------------------------------------------------===//
3079 
3080 LogicalResult CallIntrinsicOp::verify() {
3081  if (!getIntrin().starts_with("llvm."))
3082  return emitOpError() << "intrinsic name must start with 'llvm.'";
3083  return success();
3084 }
3085 
3086 //===----------------------------------------------------------------------===//
3087 // OpAsmDialectInterface
3088 //===----------------------------------------------------------------------===//
3089 
3090 namespace {
3091 struct LLVMOpAsmDialectInterface : public OpAsmDialectInterface {
3093 
3094  AliasResult getAlias(Attribute attr, raw_ostream &os) const override {
3096  .Case<AccessGroupAttr, AliasScopeAttr, AliasScopeDomainAttr,
3097  DIBasicTypeAttr, DICompileUnitAttr, DICompositeTypeAttr,
3098  DIDerivedTypeAttr, DIFileAttr, DIGlobalVariableAttr,
3099  DIGlobalVariableExpressionAttr, DILabelAttr, DILexicalBlockAttr,
3100  DILexicalBlockFileAttr, DILocalVariableAttr, DIModuleAttr,
3101  DINamespaceAttr, DINullTypeAttr, DIStringTypeAttr,
3102  DISubprogramAttr, DISubroutineTypeAttr, LoopAnnotationAttr,
3103  LoopVectorizeAttr, LoopInterleaveAttr, LoopUnrollAttr,
3104  LoopUnrollAndJamAttr, LoopLICMAttr, LoopDistributeAttr,
3105  LoopPipelineAttr, LoopPeeledAttr, LoopUnswitchAttr, TBAARootAttr,
3106  TBAATagAttr, TBAATypeDescriptorAttr>([&](auto attr) {
3107  os << decltype(attr)::getMnemonic();
3108  return AliasResult::OverridableAlias;
3109  })
3110  .Default([](Attribute) { return AliasResult::NoAlias; });
3111  }
3112 };
3113 } // namespace
3114 
3115 //===----------------------------------------------------------------------===//
3116 // LinkerOptionsOp
3117 //===----------------------------------------------------------------------===//
3118 
3119 LogicalResult LinkerOptionsOp::verify() {
3120  if (mlir::Operation *parentOp = (*this)->getParentOp();
3121  parentOp && !satisfiesLLVMModule(parentOp))
3122  return emitOpError("must appear at the module level");
3123  return success();
3124 }
3125 
3126 //===----------------------------------------------------------------------===//
3127 // InlineAsmOp
3128 //===----------------------------------------------------------------------===//
3129 
3130 void InlineAsmOp::getEffects(
3132  &effects) {
3133  if (getHasSideEffects()) {
3134  effects.emplace_back(MemoryEffects::Write::get());
3135  effects.emplace_back(MemoryEffects::Read::get());
3136  }
3137 }
3138 
3139 //===----------------------------------------------------------------------===//
3140 // masked_gather (intrinsic)
3141 //===----------------------------------------------------------------------===//
3142 
3143 LogicalResult LLVM::masked_gather::verify() {
3144  auto ptrsVectorType = getPtrs().getType();
3145  Type expectedPtrsVectorType =
3147  LLVM::getVectorNumElements(getRes().getType()));
3148  // Vector of pointers type should match result vector type, other than the
3149  // element type.
3150  if (ptrsVectorType != expectedPtrsVectorType)
3151  return emitOpError("expected operand #1 type to be ")
3152  << expectedPtrsVectorType;
3153  return success();
3154 }
3155 
3156 //===----------------------------------------------------------------------===//
3157 // masked_scatter (intrinsic)
3158 //===----------------------------------------------------------------------===//
3159 
3160 LogicalResult LLVM::masked_scatter::verify() {
3161  auto ptrsVectorType = getPtrs().getType();
3162  Type expectedPtrsVectorType =
3164  LLVM::getVectorNumElements(getValue().getType()));
3165  // Vector of pointers type should match value vector type, other than the
3166  // element type.
3167  if (ptrsVectorType != expectedPtrsVectorType)
3168  return emitOpError("expected operand #2 type to be ")
3169  << expectedPtrsVectorType;
3170  return success();
3171 }
3172 
3173 //===----------------------------------------------------------------------===//
3174 // LLVMDialect initialization, type parsing, and registration.
3175 //===----------------------------------------------------------------------===//
3176 
3177 void LLVMDialect::initialize() {
3178  registerAttributes();
3179 
3180  // clang-format off
3181  addTypes<LLVMVoidType,
3182  LLVMPPCFP128Type,
3183  LLVMTokenType,
3184  LLVMLabelType,
3185  LLVMMetadataType,
3186  LLVMStructType>();
3187  // clang-format on
3188  registerTypes();
3189 
3190  addOperations<
3191 #define GET_OP_LIST
3192 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
3193  ,
3194 #define GET_OP_LIST
3195 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
3196  >();
3197 
3198  // Support unknown operations because not all LLVM operations are registered.
3199  allowUnknownOperations();
3200  // clang-format off
3201  addInterfaces<LLVMOpAsmDialectInterface>();
3202  // clang-format on
3204 }
3205 
3206 #define GET_OP_CLASSES
3207 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
3208 
3209 #define GET_OP_CLASSES
3210 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
3211 
3212 LogicalResult LLVMDialect::verifyDataLayoutString(
3213  StringRef descr, llvm::function_ref<void(const Twine &)> reportError) {
3214  llvm::Expected<llvm::DataLayout> maybeDataLayout =
3215  llvm::DataLayout::parse(descr);
3216  if (maybeDataLayout)
3217  return success();
3218 
3219  std::string message;
3220  llvm::raw_string_ostream messageStream(message);
3221  llvm::logAllUnhandledErrors(maybeDataLayout.takeError(), messageStream);
3222  reportError("invalid data layout descriptor: " + messageStream.str());
3223  return failure();
3224 }
3225 
3226 /// Verify LLVM dialect attributes.
3227 LogicalResult LLVMDialect::verifyOperationAttribute(Operation *op,
3228  NamedAttribute attr) {
3229  // If the data layout attribute is present, it must use the LLVM data layout
3230  // syntax. Try parsing it and report errors in case of failure. Users of this
3231  // attribute may assume it is well-formed and can pass it to the (asserting)
3232  // llvm::DataLayout constructor.
3233  if (attr.getName() != LLVM::LLVMDialect::getDataLayoutAttrName())
3234  return success();
3235  if (auto stringAttr = llvm::dyn_cast<StringAttr>(attr.getValue()))
3236  return verifyDataLayoutString(
3237  stringAttr.getValue(),
3238  [op](const Twine &message) { op->emitOpError() << message.str(); });
3239 
3240  return op->emitOpError() << "expected '"
3241  << LLVM::LLVMDialect::getDataLayoutAttrName()
3242  << "' to be a string attributes";
3243 }
3244 
3245 LogicalResult LLVMDialect::verifyParameterAttribute(Operation *op,
3246  Type paramType,
3247  NamedAttribute paramAttr) {
3248  // LLVM attribute may be attached to a result of operation that has not been
3249  // converted to LLVM dialect yet, so the result may have a type with unknown
3250  // representation in LLVM dialect type space. In this case we cannot verify
3251  // whether the attribute may be
3252  bool verifyValueType = isCompatibleType(paramType);
3253  StringAttr name = paramAttr.getName();
3254 
3255  auto checkUnitAttrType = [&]() -> LogicalResult {
3256  if (!llvm::isa<UnitAttr>(paramAttr.getValue()))
3257  return op->emitError() << name << " should be a unit attribute";
3258  return success();
3259  };
3260  auto checkTypeAttrType = [&]() -> LogicalResult {
3261  if (!llvm::isa<TypeAttr>(paramAttr.getValue()))
3262  return op->emitError() << name << " should be a type attribute";
3263  return success();
3264  };
3265  auto checkIntegerAttrType = [&]() -> LogicalResult {
3266  if (!llvm::isa<IntegerAttr>(paramAttr.getValue()))
3267  return op->emitError() << name << " should be an integer attribute";
3268  return success();
3269  };
3270  auto checkPointerType = [&]() -> LogicalResult {
3271  if (!llvm::isa<LLVMPointerType>(paramType))
3272  return op->emitError()
3273  << name << " attribute attached to non-pointer LLVM type";
3274  return success();
3275  };
3276  auto checkIntegerType = [&]() -> LogicalResult {
3277  if (!llvm::isa<IntegerType>(paramType))
3278  return op->emitError()
3279  << name << " attribute attached to non-integer LLVM type";
3280  return success();
3281  };
3282  auto checkPointerTypeMatches = [&]() -> LogicalResult {
3283  if (failed(checkPointerType()))
3284  return failure();
3285 
3286  return success();
3287  };
3288 
3289  // Check a unit attribute that is attached to a pointer value.
3290  if (name == LLVMDialect::getNoAliasAttrName() ||
3291  name == LLVMDialect::getReadonlyAttrName() ||
3292  name == LLVMDialect::getReadnoneAttrName() ||
3293  name == LLVMDialect::getWriteOnlyAttrName() ||
3294  name == LLVMDialect::getNestAttrName() ||
3295  name == LLVMDialect::getNoCaptureAttrName() ||
3296  name == LLVMDialect::getNoFreeAttrName() ||
3297  name == LLVMDialect::getNonNullAttrName()) {
3298  if (failed(checkUnitAttrType()))
3299  return failure();
3300  if (verifyValueType && failed(checkPointerType()))
3301  return failure();
3302  return success();
3303  }
3304 
3305  // Check a type attribute that is attached to a pointer value.
3306  if (name == LLVMDialect::getStructRetAttrName() ||
3307  name == LLVMDialect::getByValAttrName() ||
3308  name == LLVMDialect::getByRefAttrName() ||
3309  name == LLVMDialect::getInAllocaAttrName() ||
3310  name == LLVMDialect::getPreallocatedAttrName()) {
3311  if (failed(checkTypeAttrType()))
3312  return failure();
3313  if (verifyValueType && failed(checkPointerTypeMatches()))
3314  return failure();
3315  return success();
3316  }
3317 
3318  // Check a unit attribute that is attached to an integer value.
3319  if (name == LLVMDialect::getSExtAttrName() ||
3320  name == LLVMDialect::getZExtAttrName()) {
3321  if (failed(checkUnitAttrType()))
3322  return failure();
3323  if (verifyValueType && failed(checkIntegerType()))
3324  return failure();
3325  return success();
3326  }
3327 
3328  // Check an integer attribute that is attached to a pointer value.
3329  if (name == LLVMDialect::getAlignAttrName() ||
3330  name == LLVMDialect::getDereferenceableAttrName() ||
3331  name == LLVMDialect::getDereferenceableOrNullAttrName() ||
3332  name == LLVMDialect::getStackAlignmentAttrName()) {
3333  if (failed(checkIntegerAttrType()))
3334  return failure();
3335  if (verifyValueType && failed(checkPointerType()))
3336  return failure();
3337  return success();
3338  }
3339 
3340  // Check a unit attribute that can be attached to arbitrary types.
3341  if (name == LLVMDialect::getNoUndefAttrName() ||
3342  name == LLVMDialect::getInRegAttrName() ||
3343  name == LLVMDialect::getReturnedAttrName())
3344  return checkUnitAttrType();
3345 
3346  return success();
3347 }
3348 
3349 /// Verify LLVMIR function argument attributes.
3350 LogicalResult LLVMDialect::verifyRegionArgAttribute(Operation *op,
3351  unsigned regionIdx,
3352  unsigned argIdx,
3353  NamedAttribute argAttr) {
3354  auto funcOp = dyn_cast<FunctionOpInterface>(op);
3355  if (!funcOp)
3356  return success();
3357  Type argType = funcOp.getArgumentTypes()[argIdx];
3358 
3359  return verifyParameterAttribute(op, argType, argAttr);
3360 }
3361 
3362 LogicalResult LLVMDialect::verifyRegionResultAttribute(Operation *op,
3363  unsigned regionIdx,
3364  unsigned resIdx,
3365  NamedAttribute resAttr) {
3366  auto funcOp = dyn_cast<FunctionOpInterface>(op);
3367  if (!funcOp)
3368  return success();
3369  Type resType = funcOp.getResultTypes()[resIdx];
3370 
3371  // Check to see if this function has a void return with a result attribute
3372  // to it. It isn't clear what semantics we would assign to that.
3373  if (llvm::isa<LLVMVoidType>(resType))
3374  return op->emitError() << "cannot attach result attributes to functions "
3375  "with a void return";
3376 
3377  // Check to see if this attribute is allowed as a result attribute. Only
3378  // explicitly forbidden LLVM attributes will cause an error.
3379  auto name = resAttr.getName();
3380  if (name == LLVMDialect::getAllocAlignAttrName() ||
3381  name == LLVMDialect::getAllocatedPointerAttrName() ||
3382  name == LLVMDialect::getByValAttrName() ||
3383  name == LLVMDialect::getByRefAttrName() ||
3384  name == LLVMDialect::getInAllocaAttrName() ||
3385  name == LLVMDialect::getNestAttrName() ||
3386  name == LLVMDialect::getNoCaptureAttrName() ||
3387  name == LLVMDialect::getNoFreeAttrName() ||
3388  name == LLVMDialect::getPreallocatedAttrName() ||
3389  name == LLVMDialect::getReadnoneAttrName() ||
3390  name == LLVMDialect::getReadonlyAttrName() ||
3391  name == LLVMDialect::getReturnedAttrName() ||
3392  name == LLVMDialect::getStackAlignmentAttrName() ||
3393  name == LLVMDialect::getStructRetAttrName() ||
3394  name == LLVMDialect::getWriteOnlyAttrName())
3395  return op->emitError() << name << " is not a valid result attribute";
3396  return verifyParameterAttribute(op, resType, resAttr);
3397 }
3398 
3400  Type type, Location loc) {
3401  // If this was folded from an operation other than llvm.mlir.constant, it
3402  // should be materialized as such. Note that an llvm.mlir.zero may fold into
3403  // a builtin zero attribute and thus will materialize as a llvm.mlir.constant.
3404  if (auto symbol = dyn_cast<FlatSymbolRefAttr>(value))
3405  if (isa<LLVM::LLVMPointerType>(type))
3406  return builder.create<LLVM::AddressOfOp>(loc, type, symbol);
3407  if (isa<LLVM::UndefAttr>(value))
3408  return builder.create<LLVM::UndefOp>(loc, type);
3409  if (isa<LLVM::PoisonAttr>(value))
3410  return builder.create<LLVM::PoisonOp>(loc, type);
3411  if (isa<LLVM::ZeroAttr>(value))
3412  return builder.create<LLVM::ZeroOp>(loc, type);
3413  // Otherwise try materializing it as a regular llvm.mlir.constant op.
3414  return LLVM::ConstantOp::materialize(builder, value, type, loc);
3415 }
3416 
3417 //===----------------------------------------------------------------------===//
3418 // Utility functions.
3419 //===----------------------------------------------------------------------===//
3420 
3422  StringRef name, StringRef value,
3423  LLVM::Linkage linkage) {
3424  assert(builder.getInsertionBlock() &&
3425  builder.getInsertionBlock()->getParentOp() &&
3426  "expected builder to point to a block constrained in an op");
3427  auto module =
3428  builder.getInsertionBlock()->getParentOp()->getParentOfType<ModuleOp>();
3429  assert(module && "builder points to an op outside of a module");
3430 
3431  // Create the global at the entry of the module.
3432  OpBuilder moduleBuilder(module.getBodyRegion(), builder.getListener());
3433  MLIRContext *ctx = builder.getContext();
3434  auto type = LLVM::LLVMArrayType::get(IntegerType::get(ctx, 8), value.size());
3435  auto global = moduleBuilder.create<LLVM::GlobalOp>(
3436  loc, type, /*isConstant=*/true, linkage, name,
3437  builder.getStringAttr(value), /*alignment=*/0);
3438 
3439  LLVMPointerType ptrType = LLVMPointerType::get(ctx);
3440  // Get the pointer to the first character in the global string.
3441  Value globalPtr =
3442  builder.create<LLVM::AddressOfOp>(loc, ptrType, global.getSymNameAttr());
3443  return builder.create<LLVM::GEPOp>(loc, ptrType, type, globalPtr,
3444  ArrayRef<GEPArg>{0, 0});
3445 }
3446 
3448  return op->hasTrait<OpTrait::SymbolTable>() &&
3450 }
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:142
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)
LogicalResult verifyCallOpVarCalleeType(OpTy callOp)
Verify that the parameter and return types of the variadic callee type match the callOp argument and ...
static ParseResult parseGEPIndices(OpAsmParser &parser, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &indices, DenseI32ArrayAttr &rawConstantIndices)
static ParseResult parseCmpOp(OpAsmParser &parser, OperationState &result)
static ParseResult parseLLVMOpAttrs(OpAsmParser &parser, NamedAttrList &result)
LogicalResult verifyAtomicMemOp(OpTy memOp, Type valueType, ArrayRef< AtomicOrdering > unsupportedOrderings)
Verifies the attributes and the type of atomic memory access operations.
static LogicalResult verifyComdat(Operation *op, std::optional< SymbolRefAttr > attr)
static RetTy parseOptionalLLVMKeyword(OpAsmParser &parser, OperationState &result, EnumTy defaultValue)
Parse an enum from the keyword, or default to the provided default value.
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 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 printShuffleType(AsmPrinter &printer, Operation *op, Type v1Type, Type resType, DenseI32ArrayAttr mask)
Nothing to do when the result type is inferred.
static Type buildLLVMFunctionType(OpAsmParser &parser, SMLoc loc, ArrayRef< Type > inputs, ArrayRef< Type > outputs, function_interface_impl::VariadicFlag variadicFlag)
static auto processFMFAttr(ArrayRef< NamedAttribute > attrs)
static Operation * parentLLVMModule(Operation *op)
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 void printOverflowFlags(AsmPrinter &p, Operation *op, IntegerOverflowFlags flags)
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 ParseResult parseOverflowFlags(AsmParser &p, IntegerOverflowFlags &flags)
Definition: LLVMDialect.cpp:78
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....
static Type extractVectorElementType(Type type)
Returns the elemental type of any LLVM-compatible vector type or self.
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 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.
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[]
static ParseResult parseInsertExtractValueElementType(AsmParser &parser, Type &valueType, Type containerType, DenseI64ArrayAttr position)
Infer the value type from the container type and position.
static void printLLVMOpAttrs(OpAsmPrinter &printer, Operation *op, DictionaryAttr attrs)
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 ParseResult parseCallTypeAndResolveOperands(OpAsmParser &parser, OperationState &result, bool isDirect, ArrayRef< OpAsmParser::UnresolvedOperand > operands)
Parses the type of a call operation and resolves the operands if the parsing succeeds.
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 Type getElementType(Type type, ArrayRef< int32_t > indices, function_ref< InFlightDiagnostic(StringRef)> emitErrorFn)
Walks the given type hierarchy with the given indices, potentially down to component granularity,...
Definition: SPIRVOps.cpp:215
The possible results of an alias query.
Definition: AliasAnalysis.h:26
@ NoAlias
The two locations do not alias at all.
Definition: AliasAnalysis.h:34
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.
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:73
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 parseLess()=0
Parse a '<' 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 parseGreater()=0
Parse a '>' token.
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 parseKeyword(StringRef keyword)
Parse a given keyword.
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 printSymbolName(StringRef symbolRef)
Print the given string as a symbol reference, i.e.
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:31
bool empty()
Definition: Block.h:146
BlockArgument getArgument(unsigned i)
Definition: Block.h:127
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
Definition: Block.cpp:152
Operation & front()
Definition: Block.h:151
Operation * getParentOp()
Returns the closest surrounding operation that contains this block.
Definition: Block.cpp:30
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:118
IntegerAttr getI32IntegerAttr(int32_t value)
Definition: Builders.cpp:220
DenseI32ArrayAttr getDenseI32ArrayAttr(ArrayRef< int32_t > values)
Definition: Builders.cpp:183
IntegerAttr getI64IntegerAttr(int64_t value)
Definition: Builders.cpp:132
StringAttr getStringAttr(const Twine &bytes)
Definition: Builders.cpp:273
TypedAttr getZeroAttr(Type type)
Definition: Builders.cpp:335
MLIRContext * getContext() const
Definition: Builders.h:55
Attr getAttr(Args &&...args)
Get or construct an instance of the attribute Attr with provided arguments.
Definition: Builders.h:101
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.
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:148
This class represents a diagnostic that is inflight and set to be reported.
Definition: Diagnostics.h:313
Diagnostic & attachNote(std::optional< Location > noteLoc=std::nullopt)
Attaches a note to this diagnostic.
Definition: Diagnostics.h:351
Class used for building a 'llvm.getelementptr'.
Definition: LLVMDialect.h:74
Class used for convenient access and iteration over GEP indices.
Definition: LLVMDialect.h:114
std::conditional_t< std::is_base_of< Attribute, llvm::detail::ValueOfRange< DynamicRange > >::value, Attribute, PointerUnion< IntegerAttr, llvm::detail::ValueOfRange< DynamicRange > >> value_type
Return type of 'operator[]' and the iterators 'operator*'.
Definition: LLVMDialect.h:125
bool isDynamicIndex(size_t index) const
Returns whether the GEP index at the given position is a dynamic index.
Definition: LLVMDialect.h:143
size_t size() const
Returns the amount of indices of the GEPOp.
Definition: LLVMDialect.h:148
LLVM dialect structure type representing a collection of different-typed elements manipulated togethe...
Definition: LLVMTypes.h:108
ArrayRef< Type > getBody() const
Returns the list of element types contained in a non-opaque struct.
Definition: LLVMTypes.cpp:490
T findInstanceOf()
Return an instance of the given location type if one is nested under the current location.
Definition: Location.h:41
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:63
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:60
This class provides a mutable adaptor for a range of operands.
Definition: ValueRange.h:115
NamedAttrList is array of NamedAttributes that tracks whether it is sorted and does some basic work t...
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.
Attribute set(StringAttr name, Attribute value)
If the an attribute exists with the specified name, change it to the new value.
void append(StringRef name, Attribute attr)
Add an attribute with the specified name.
NamedAttribute represents a combination of a name and an Attribute value.
Definition: Attributes.h:207
StringAttr getName() const
Return the name of the attribute.
Definition: Attributes.cpp:49
Attribute getValue() const
Return the value of the attribute.
Definition: Attributes.h:221
OpAsmDialectInterface(Dialect *dialect)
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
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.
virtual void printOptionalAttrDict(ArrayRef< NamedAttribute > attrs, ArrayRef< StringRef > elidedAttrs={})=0
If the specified operation has attributes, print out an attribute dictionary with their values.
void printFunctionalType(Operation *op)
Print the complete type of an operation in functional form.
Definition: AsmPrinter.cpp:94
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:351
This class helps build Operations.
Definition: Builders.h:210
Listener * getListener() const
Returns the current listener of this builder, or nullptr if this builder doesn't have a listener.
Definition: Builders.h:323
Block * createBlock(Region *parent, Region::iterator insertPt={}, TypeRange argTypes=std::nullopt, ArrayRef< Location > locs=std::nullopt)
Add new block with 'argTypes' arguments and set the insertion point to the end of it.
Definition: Builders.cpp:441
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
Definition: Builders.cpp:468
Block * getInsertionBlock() const
Return the block the current insertion point belongs to.
Definition: Builders.h:445
This class represents a single result from folding an operation.
Definition: OpDefinition.h:268
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:435
This class represents a contiguous range of operand ranges, e.g.
Definition: ValueRange.h:82
This class implements the operand iterators for the Operation class.
Definition: ValueRange.h:42
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:745
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Definition: Operation.h:402
Location getLoc()
The source location the operation was defined or derived from.
Definition: Operation.h:223
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:268
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:671
This class implements Optional functionality for ParseResult.
Definition: OpDefinition.h:39
ParseResult value() const
Access the internal ParseResult value.
Definition: OpDefinition.h:52
bool has_value() const
Returns true if we contain a valid ParseResult value.
Definition: OpDefinition.h:49
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
Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
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:92
This class provides an abstraction over the various different ranges of value types.
Definition: TypeRange.h:36
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:126
This class provides an abstraction over the different types of ranges over Values.
Definition: ValueRange.h:381
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:129
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
Definition: Value.cpp:20
static WalkResult skip()
Definition: Visitors.h:52
static WalkResult advance()
Definition: Visitors.h:51
static WalkResult interrupt()
Definition: Visitors.h:50
static DenseArrayAttrImpl get(MLIRContext *context, ArrayRef< int32_t > content)
Builder from ArrayRef<T>.
A named class for passing around the variadic flag.
void addLLVMInlinerInterface(LLVMDialect *dialect)
Register the LLVMInlinerInterface implementation of DialectInlinerInterface with the LLVM dialect.
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...
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:926
bool isScalableVectorType(Type vectorType)
Returns whether a vector type is scalable or not.
Definition: LLVMTypes.cpp:917
bool isCompatibleVectorType(Type type)
Returns true if the given type is a vector type compatible with the LLVM dialect.
Definition: LLVMTypes.cpp:874
bool isCompatibleOuterType(Type type)
Returns true if the given outer type is compatible with the LLVM dialect without checking its potenti...
Definition: LLVMTypes.cpp:763
bool satisfiesLLVMModule(Operation *op)
LLVM requires some operations to be inside of a Module operation.
llvm::PointerEmbeddedInt< int32_t, kGEPConstantBitWidth > GEPConstantIndex
Wrapper around a int32_t for use in a PointerUnion.
Definition: LLVMDialect.h:68
constexpr int kGEPConstantBitWidth
Bit-width of a 'GEPConstantIndex' within GEPArg.
Definition: LLVMDialect.h:65
bool isCompatibleType(Type type)
Returns true if the given type is compatible with the LLVM dialect.
Definition: LLVMTypes.cpp:856
bool isCompatibleFloatingPointType(Type type)
Returns true if the given type is a floating-point type compatible with the LLVM dialect.
Definition: LLVMTypes.cpp:869
llvm::ElementCount getVectorNumElements(Type type)
Returns the element count of any LLVM-compatible vector type.
Definition: LLVMTypes.cpp:899
Type getVectorElementType(Type type)
Returns the element type of any vector type compatible with the LLVM dialect.
Definition: LLVMTypes.cpp:890
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:136
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
Definition: Matchers.h:285
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,...
ParseResult parseFunctionSignature(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:20
Value constantIndex(OpBuilder &builder, Location loc, int64_t i)
Generates a constant of index type.
Definition: CodegenUtils.h:334
Visibility
This enum describes C++ inheritance visibility.
Definition: Class.h:407
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:401
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:438
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
Definition: Utils.cpp:305
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...
Attribute convertToAttribute(MLIRContext *ctx, int64_t storage)
Convert the provided int64_t to an IntegerAttr attribute.
Definition: ODSSupport.cpp:32
LogicalResult convertFromAttribute(int64_t &storage, Attribute attr, function_ref< InFlightDiagnostic()> emitError)
Convert an IntegerAttr attribute to an int64_t, or return an error if the attribute isn't an IntegerA...
Definition: ODSSupport.cpp:22
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
Definition: Verifier.cpp:421
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.
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.