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