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