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