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