MLIR  16.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 //===----------------------------------------------------------------------===//
14 #include "TypeDetail.h"
16 #include "mlir/IR/Builders.h"
17 #include "mlir/IR/BuiltinOps.h"
18 #include "mlir/IR/BuiltinTypes.h"
21 #include "mlir/IR/MLIRContext.h"
22 #include "mlir/IR/Matchers.h"
23 
24 #include "llvm/ADT/TypeSwitch.h"
25 #include "llvm/AsmParser/Parser.h"
26 #include "llvm/Bitcode/BitcodeReader.h"
27 #include "llvm/Bitcode/BitcodeWriter.h"
28 #include "llvm/IR/Attributes.h"
29 #include "llvm/IR/Function.h"
30 #include "llvm/IR/Type.h"
31 #include "llvm/Support/Error.h"
32 #include "llvm/Support/Mutex.h"
33 #include "llvm/Support/SourceMgr.h"
34 
35 #include <numeric>
36 
37 using namespace mlir;
38 using namespace mlir::LLVM;
39 using mlir::LLVM::cconv::getMaxEnumValForCConv;
40 using mlir::LLVM::linkage::getMaxEnumValForLinkage;
41 
42 #include "mlir/Dialect/LLVMIR/LLVMOpsDialect.cpp.inc"
43 
44 static constexpr const char kVolatileAttrName[] = "volatile_";
45 static constexpr const char kNonTemporalAttrName[] = "nontemporal";
46 static constexpr const char kElemTypeAttrName[] = "elem_type";
47 
48 #include "mlir/Dialect/LLVMIR/LLVMOpsInterfaces.cpp.inc"
49 
51  SmallVector<NamedAttribute, 8> filteredAttrs(
52  llvm::make_filter_range(attrs, [&](NamedAttribute attr) {
53  if (attr.getName() == "fastmathFlags") {
54  auto defAttr =
55  FastmathFlagsAttr::get(attr.getValue().getContext(), {});
56  return defAttr != attr.getValue();
57  }
58  return true;
59  }));
60  return filteredAttrs;
61 }
62 
64  NamedAttrList &result) {
65  return parser.parseOptionalAttrDict(result);
66 }
67 
68 static void printLLVMOpAttrs(OpAsmPrinter &printer, Operation *op,
69  DictionaryAttr attrs) {
70  printer.printOptionalAttrDict(processFMFAttr(attrs.getValue()));
71 }
72 
73 /// Verifies `symbol`'s use in `op` to ensure the symbol is a valid and
74 /// fully defined llvm.func.
76  Operation *op,
77  SymbolTableCollection &symbolTable) {
78  StringRef name = symbol.getValue();
79  auto func =
80  symbolTable.lookupNearestSymbolFrom<LLVMFuncOp>(op, symbol.getAttr());
81  if (!func)
82  return op->emitOpError("'")
83  << name << "' does not reference a valid LLVM function";
84  if (func.isExternal())
85  return op->emitOpError("'") << name << "' does not have a definition";
86  return success();
87 }
88 
89 /// Returns a boolean type that has the same shape as `type`. It supports both
90 /// fixed size vectors as well as scalable vectors.
91 static Type getI1SameShape(Type type) {
92  Type i1Type = IntegerType::get(type.getContext(), 1);
94  return LLVM::getVectorType(i1Type, LLVM::getVectorNumElements(type));
95  return i1Type;
96 }
97 
98 //===----------------------------------------------------------------------===//
99 // Printing, parsing and builder for LLVM::CmpOp.
100 //===----------------------------------------------------------------------===//
101 
102 void ICmpOp::build(OpBuilder &builder, OperationState &result,
103  ICmpPredicate predicate, Value lhs, Value rhs) {
104  build(builder, result, getI1SameShape(lhs.getType()), predicate, lhs, rhs);
105 }
106 
107 void FCmpOp::build(OpBuilder &builder, OperationState &result,
108  FCmpPredicate predicate, Value lhs, Value rhs) {
109  build(builder, result, getI1SameShape(lhs.getType()), predicate, lhs, rhs);
110 }
111 
112 void ICmpOp::print(OpAsmPrinter &p) {
113  p << " \"" << stringifyICmpPredicate(getPredicate()) << "\" " << getOperand(0)
114  << ", " << getOperand(1);
115  p.printOptionalAttrDict((*this)->getAttrs(), {"predicate"});
116  p << " : " << getLhs().getType();
117 }
118 
119 void FCmpOp::print(OpAsmPrinter &p) {
120  p << " \"" << stringifyFCmpPredicate(getPredicate()) << "\" " << getOperand(0)
121  << ", " << getOperand(1);
122  p.printOptionalAttrDict(processFMFAttr((*this)->getAttrs()), {"predicate"});
123  p << " : " << getLhs().getType();
124 }
125 
126 // <operation> ::= `llvm.icmp` string-literal ssa-use `,` ssa-use
127 // attribute-dict? `:` type
128 // <operation> ::= `llvm.fcmp` string-literal ssa-use `,` ssa-use
129 // attribute-dict? `:` type
130 template <typename CmpPredicateType>
132  StringAttr predicateAttr;
134  Type type;
135  SMLoc predicateLoc, trailingTypeLoc;
136  if (parser.getCurrentLocation(&predicateLoc) ||
137  parser.parseAttribute(predicateAttr, "predicate", result.attributes) ||
138  parser.parseOperand(lhs) || parser.parseComma() ||
139  parser.parseOperand(rhs) ||
140  parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
141  parser.getCurrentLocation(&trailingTypeLoc) || parser.parseType(type) ||
142  parser.resolveOperand(lhs, type, result.operands) ||
143  parser.resolveOperand(rhs, type, result.operands))
144  return failure();
145 
146  // Replace the string attribute `predicate` with an integer attribute.
147  int64_t predicateValue = 0;
148  if (std::is_same<CmpPredicateType, ICmpPredicate>()) {
149  Optional<ICmpPredicate> predicate =
150  symbolizeICmpPredicate(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  } else {
157  Optional<FCmpPredicate> predicate =
158  symbolizeFCmpPredicate(predicateAttr.getValue());
159  if (!predicate)
160  return parser.emitError(predicateLoc)
161  << "'" << predicateAttr.getValue()
162  << "' is an incorrect value of the 'predicate' attribute";
163  predicateValue = static_cast<int64_t>(*predicate);
164  }
165 
166  result.attributes.set("predicate",
167  parser.getBuilder().getI64IntegerAttr(predicateValue));
168 
169  // The result type is either i1 or a vector type <? x i1> if the inputs are
170  // vectors.
171  if (!isCompatibleType(type))
172  return parser.emitError(trailingTypeLoc,
173  "expected LLVM dialect-compatible type");
174  result.addTypes(getI1SameShape(type));
175  return success();
176 }
177 
178 ParseResult ICmpOp::parse(OpAsmParser &parser, OperationState &result) {
179  return parseCmpOp<ICmpPredicate>(parser, result);
180 }
181 
182 ParseResult FCmpOp::parse(OpAsmParser &parser, OperationState &result) {
183  return parseCmpOp<FCmpPredicate>(parser, result);
184 }
185 
186 //===----------------------------------------------------------------------===//
187 // Printing, parsing and verification for LLVM::AllocaOp.
188 //===----------------------------------------------------------------------===//
189 
190 void AllocaOp::print(OpAsmPrinter &p) {
191  Type elemTy = getType().cast<LLVM::LLVMPointerType>().getElementType();
192  if (!elemTy)
193  elemTy = *getElemType();
194 
195  auto funcTy =
196  FunctionType::get(getContext(), {getArraySize().getType()}, {getType()});
197 
198  p << ' ' << getArraySize() << " x " << elemTy;
199  if (getAlignment() && *getAlignment() != 0)
200  p.printOptionalAttrDict((*this)->getAttrs(), {kElemTypeAttrName});
201  else
202  p.printOptionalAttrDict((*this)->getAttrs(),
203  {"alignment", kElemTypeAttrName});
204  p << " : " << funcTy;
205 }
206 
207 // <operation> ::= `llvm.alloca` ssa-use `x` type attribute-dict?
208 // `:` type `,` type
209 ParseResult AllocaOp::parse(OpAsmParser &parser, OperationState &result) {
211  Type type, elemType;
212  SMLoc trailingTypeLoc;
213  if (parser.parseOperand(arraySize) || parser.parseKeyword("x") ||
214  parser.parseType(elemType) ||
215  parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
216  parser.getCurrentLocation(&trailingTypeLoc) || parser.parseType(type))
217  return failure();
218 
219  Optional<NamedAttribute> alignmentAttr =
220  result.attributes.getNamed("alignment");
221  if (alignmentAttr.has_value()) {
222  auto alignmentInt =
223  alignmentAttr.value().getValue().dyn_cast<IntegerAttr>();
224  if (!alignmentInt)
225  return parser.emitError(parser.getNameLoc(),
226  "expected integer alignment");
227  if (alignmentInt.getValue().isNullValue())
228  result.attributes.erase("alignment");
229  }
230 
231  // Extract the result type from the trailing function type.
232  auto funcType = type.dyn_cast<FunctionType>();
233  if (!funcType || funcType.getNumInputs() != 1 ||
234  funcType.getNumResults() != 1)
235  return parser.emitError(
236  trailingTypeLoc,
237  "expected trailing function type with one argument and one result");
238 
239  if (parser.resolveOperand(arraySize, funcType.getInput(0), result.operands))
240  return failure();
241 
242  Type resultType = funcType.getResult(0);
243  if (auto ptrResultType = resultType.dyn_cast<LLVMPointerType>()) {
244  if (ptrResultType.isOpaque())
245  result.addAttribute(kElemTypeAttrName, TypeAttr::get(elemType));
246  }
247 
248  result.addTypes({funcType.getResult(0)});
249  return success();
250 }
251 
252 /// Checks that the elemental type is present in either the pointer type or
253 /// the attribute, but not both.
254 static LogicalResult verifyOpaquePtr(Operation *op, LLVMPointerType ptrType,
255  Optional<Type> ptrElementType) {
256  if (ptrType.isOpaque() && !ptrElementType.has_value()) {
257  return op->emitOpError() << "expected '" << kElemTypeAttrName
258  << "' attribute if opaque pointer type is used";
259  }
260  if (!ptrType.isOpaque() && ptrElementType.has_value()) {
261  return op->emitOpError()
262  << "unexpected '" << kElemTypeAttrName
263  << "' attribute when non-opaque pointer type is used";
264  }
265  return success();
266 }
267 
269  return verifyOpaquePtr(getOperation(), getType().cast<LLVMPointerType>(),
270  getElemType());
271 }
272 
273 //===----------------------------------------------------------------------===//
274 // LLVM::BrOp
275 //===----------------------------------------------------------------------===//
276 
277 SuccessorOperands BrOp::getSuccessorOperands(unsigned index) {
278  assert(index == 0 && "invalid successor index");
279  return SuccessorOperands(getDestOperandsMutable());
280 }
281 
282 //===----------------------------------------------------------------------===//
283 // LLVM::CondBrOp
284 //===----------------------------------------------------------------------===//
285 
286 SuccessorOperands CondBrOp::getSuccessorOperands(unsigned index) {
287  assert(index < getNumSuccessors() && "invalid successor index");
288  return SuccessorOperands(index == 0 ? getTrueDestOperandsMutable()
289  : getFalseDestOperandsMutable());
290 }
291 
292 //===----------------------------------------------------------------------===//
293 // LLVM::SwitchOp
294 //===----------------------------------------------------------------------===//
295 
296 void SwitchOp::build(OpBuilder &builder, OperationState &result, Value value,
297  Block *defaultDestination, ValueRange defaultOperands,
298  ArrayRef<int32_t> caseValues, BlockRange caseDestinations,
299  ArrayRef<ValueRange> caseOperands,
300  ArrayRef<int32_t> branchWeights) {
301  ElementsAttr caseValuesAttr;
302  if (!caseValues.empty())
303  caseValuesAttr = builder.getI32VectorAttr(caseValues);
304 
305  ElementsAttr weightsAttr;
306  if (!branchWeights.empty())
307  weightsAttr = builder.getI32VectorAttr(llvm::to_vector<4>(branchWeights));
308 
309  build(builder, result, value, defaultOperands, caseOperands, caseValuesAttr,
310  weightsAttr, defaultDestination, caseDestinations);
311 }
312 
313 /// <cases> ::= integer `:` bb-id (`(` ssa-use-and-type-list `)`)?
314 /// ( `,` integer `:` bb-id (`(` ssa-use-and-type-list `)`)? )?
316  OpAsmParser &parser, Type flagType, ElementsAttr &caseValues,
317  SmallVectorImpl<Block *> &caseDestinations,
319  SmallVectorImpl<SmallVector<Type>> &caseOperandTypes) {
320  SmallVector<APInt> values;
321  unsigned bitWidth = flagType.getIntOrFloatBitWidth();
322  do {
323  int64_t value = 0;
324  OptionalParseResult integerParseResult = parser.parseOptionalInteger(value);
325  if (values.empty() && !integerParseResult.has_value())
326  return success();
327 
328  if (!integerParseResult.has_value() || integerParseResult.value())
329  return failure();
330  values.push_back(APInt(bitWidth, value));
331 
332  Block *destination;
334  SmallVector<Type> operandTypes;
335  if (parser.parseColon() || parser.parseSuccessor(destination))
336  return failure();
337  if (!parser.parseOptionalLParen()) {
338  if (parser.parseOperandList(operands, OpAsmParser::Delimiter::None,
339  /*allowResultNumber=*/false) ||
340  parser.parseColonTypeList(operandTypes) || parser.parseRParen())
341  return failure();
342  }
343  caseDestinations.push_back(destination);
344  caseOperands.emplace_back(operands);
345  caseOperandTypes.emplace_back(operandTypes);
346  } while (!parser.parseOptionalComma());
347 
348  ShapedType caseValueType =
349  VectorType::get(static_cast<int64_t>(values.size()), flagType);
350  caseValues = DenseIntElementsAttr::get(caseValueType, values);
351  return success();
352 }
353 
354 static void printSwitchOpCases(OpAsmPrinter &p, SwitchOp op, Type flagType,
355  ElementsAttr caseValues,
356  SuccessorRange caseDestinations,
357  OperandRangeRange caseOperands,
358  const TypeRangeRange &caseOperandTypes) {
359  if (!caseValues)
360  return;
361 
362  size_t index = 0;
363  llvm::interleave(
364  llvm::zip(caseValues.cast<DenseIntElementsAttr>(), caseDestinations),
365  [&](auto i) {
366  p << " ";
367  p << std::get<0>(i).getLimitedValue();
368  p << ": ";
369  p.printSuccessorAndUseList(std::get<1>(i), caseOperands[index++]);
370  },
371  [&] {
372  p << ',';
373  p.printNewline();
374  });
375  p.printNewline();
376 }
377 
379  if ((!getCaseValues() && !getCaseDestinations().empty()) ||
380  (getCaseValues() &&
381  getCaseValues()->size() !=
382  static_cast<int64_t>(getCaseDestinations().size())))
383  return emitOpError("expects number of case values to match number of "
384  "case destinations");
385  if (getBranchWeights() && getBranchWeights()->size() != getNumSuccessors())
386  return emitError("expects number of branch weights to match number of "
387  "successors: ")
388  << getBranchWeights()->size() << " vs " << getNumSuccessors();
389  return success();
390 }
391 
392 SuccessorOperands SwitchOp::getSuccessorOperands(unsigned index) {
393  assert(index < getNumSuccessors() && "invalid successor index");
394  return SuccessorOperands(index == 0 ? getDefaultOperandsMutable()
395  : getCaseOperandsMutable(index - 1));
396 }
397 
398 //===----------------------------------------------------------------------===//
399 // Code for LLVM::GEPOp.
400 //===----------------------------------------------------------------------===//
401 
402 constexpr int32_t GEPOp::kDynamicIndex;
403 
405  return GEPIndicesAdaptor<ValueRange>(getRawConstantIndicesAttr(),
406  getDynamicIndices());
407 }
408 
409 /// Returns the elemental type of any LLVM-compatible vector type or self.
411  if (auto vectorType = type.dyn_cast<VectorType>())
412  return vectorType.getElementType();
413  if (auto scalableVectorType = type.dyn_cast<LLVMScalableVectorType>())
414  return scalableVectorType.getElementType();
415  if (auto fixedVectorType = type.dyn_cast<LLVMFixedVectorType>())
416  return fixedVectorType.getElementType();
417  return type;
418 }
419 
420 void GEPOp::build(OpBuilder &builder, OperationState &result, Type resultType,
421  Value basePtr, ArrayRef<GEPArg> indices,
422  ArrayRef<NamedAttribute> attributes) {
423  auto ptrType =
424  extractVectorElementType(basePtr.getType()).cast<LLVMPointerType>();
425  assert(!ptrType.isOpaque() &&
426  "expected non-opaque pointer, provide elementType explicitly when "
427  "opaque pointers are used");
428  build(builder, result, resultType, ptrType.getElementType(), basePtr, indices,
429  attributes);
430 }
431 
432 /// Destructures the 'indices' parameter into 'rawConstantIndices' and
433 /// 'dynamicIndices', encoding the former in the process. In the process,
434 /// dynamic indices which are used to index into a structure type are converted
435 /// to constant indices when possible. To do this, the GEPs element type should
436 /// be passed as first parameter.
437 static void destructureIndices(Type currType, ArrayRef<GEPArg> indices,
438  SmallVectorImpl<int32_t> &rawConstantIndices,
439  SmallVectorImpl<Value> &dynamicIndices) {
440  for (const GEPArg &iter : indices) {
441  // If the thing we are currently indexing into is a struct we must turn
442  // any integer constants into constant indices. If this is not possible
443  // we don't do anything here. The verifier will catch it and emit a proper
444  // error. All other canonicalization is done in the fold method.
445  bool requiresConst = !rawConstantIndices.empty() &&
446  currType.isa_and_nonnull<LLVMStructType>();
447  if (Value val = iter.dyn_cast<Value>()) {
448  APInt intC;
449  if (requiresConst && matchPattern(val, m_ConstantInt(&intC)) &&
450  intC.isSignedIntN(kGEPConstantBitWidth)) {
451  rawConstantIndices.push_back(intC.getSExtValue());
452  } else {
453  rawConstantIndices.push_back(GEPOp::kDynamicIndex);
454  dynamicIndices.push_back(val);
455  }
456  } else {
457  rawConstantIndices.push_back(iter.get<GEPConstantIndex>());
458  }
459 
460  // Skip for very first iteration of this loop. First index does not index
461  // within the aggregates, but is just a pointer offset.
462  if (rawConstantIndices.size() == 1 || !currType)
463  continue;
464 
465  currType =
466  TypeSwitch<Type, Type>(currType)
467  .Case<VectorType, LLVMScalableVectorType, LLVMFixedVectorType,
468  LLVMArrayType>([](auto containerType) {
469  return containerType.getElementType();
470  })
471  .Case([&](LLVMStructType structType) -> Type {
472  int64_t memberIndex = rawConstantIndices.back();
473  if (memberIndex >= 0 && static_cast<size_t>(memberIndex) <
474  structType.getBody().size())
475  return structType.getBody()[memberIndex];
476  return nullptr;
477  })
478  .Default(Type(nullptr));
479  }
480 }
481 
482 void GEPOp::build(OpBuilder &builder, OperationState &result, Type resultType,
483  Type elementType, Value basePtr, ArrayRef<GEPArg> indices,
484  ArrayRef<NamedAttribute> attributes) {
485  SmallVector<int32_t> rawConstantIndices;
486  SmallVector<Value> dynamicIndices;
487  destructureIndices(elementType, indices, rawConstantIndices, dynamicIndices);
488 
489  result.addTypes(resultType);
490  result.addAttributes(attributes);
491  result.addAttribute(getRawConstantIndicesAttrName(result.name),
492  builder.getDenseI32ArrayAttr(rawConstantIndices));
493  if (extractVectorElementType(basePtr.getType())
494  .cast<LLVMPointerType>()
495  .isOpaque())
496  result.addAttribute(kElemTypeAttrName, TypeAttr::get(elementType));
497  result.addOperands(basePtr);
498  result.addOperands(dynamicIndices);
499 }
500 
501 void GEPOp::build(OpBuilder &builder, OperationState &result, Type resultType,
502  Value basePtr, ValueRange indices,
503  ArrayRef<NamedAttribute> attributes) {
504  build(builder, result, resultType, basePtr, SmallVector<GEPArg>(indices),
505  attributes);
506 }
507 
508 void GEPOp::build(OpBuilder &builder, OperationState &result, Type resultType,
509  Type elementType, Value basePtr, ValueRange indices,
510  ArrayRef<NamedAttribute> attributes) {
511  build(builder, result, resultType, elementType, basePtr,
512  SmallVector<GEPArg>(indices), attributes);
513 }
514 
515 static ParseResult
518  DenseI32ArrayAttr &rawConstantIndices) {
519  SmallVector<int32_t> constantIndices;
520 
521  auto idxParser = [&]() -> ParseResult {
522  int32_t constantIndex;
523  OptionalParseResult parsedInteger =
525  if (parsedInteger.has_value()) {
526  if (failed(parsedInteger.value()))
527  return failure();
528  constantIndices.push_back(constantIndex);
529  return success();
530  }
531 
532  constantIndices.push_back(LLVM::GEPOp::kDynamicIndex);
533  return parser.parseOperand(indices.emplace_back());
534  };
535  if (parser.parseCommaSeparatedList(idxParser))
536  return failure();
537 
538  rawConstantIndices =
539  DenseI32ArrayAttr::get(parser.getContext(), constantIndices);
540  return success();
541 }
542 
543 static void printGEPIndices(OpAsmPrinter &printer, LLVM::GEPOp gepOp,
544  OperandRange indices,
545  DenseI32ArrayAttr rawConstantIndices) {
546  llvm::interleaveComma(
547  GEPIndicesAdaptor<OperandRange>(rawConstantIndices, indices), printer,
549  if (Value val = cst.dyn_cast<Value>())
550  printer.printOperand(val);
551  else
552  printer << cst.get<IntegerAttr>().getInt();
553  });
554 }
555 
556 namespace {
557 /// Base class for llvm::Error related to GEP index.
558 class GEPIndexError : public llvm::ErrorInfo<GEPIndexError> {
559 protected:
560  unsigned indexPos;
561 
562 public:
563  static char ID;
564 
565  std::error_code convertToErrorCode() const override {
566  return llvm::inconvertibleErrorCode();
567  }
568 
569  explicit GEPIndexError(unsigned pos) : indexPos(pos) {}
570 };
571 
572 /// llvm::Error for out-of-bound GEP index.
573 struct GEPIndexOutOfBoundError
574  : public llvm::ErrorInfo<GEPIndexOutOfBoundError, GEPIndexError> {
575  static char ID;
576 
577  using ErrorInfo::ErrorInfo;
578 
579  void log(llvm::raw_ostream &os) const override {
580  os << "index " << indexPos << " indexing a struct is out of bounds";
581  }
582 };
583 
584 /// llvm::Error for non-static GEP index indexing a struct.
585 struct GEPStaticIndexError
586  : public llvm::ErrorInfo<GEPStaticIndexError, GEPIndexError> {
587  static char ID;
588 
589  using ErrorInfo::ErrorInfo;
590 
591  void log(llvm::raw_ostream &os) const override {
592  os << "expected index " << indexPos << " indexing a struct "
593  << "to be constant";
594  }
595 };
596 } // end anonymous namespace
597 
598 char GEPIndexError::ID = 0;
600 char GEPStaticIndexError::ID = 0;
601 
602 /// For the given `structIndices` and `indices`, check if they're complied
603 /// with `baseGEPType`, especially check against LLVMStructTypes nested within.
604 static llvm::Error verifyStructIndices(Type baseGEPType, unsigned indexPos,
606  if (indexPos >= indices.size())
607  // Stop searching
608  return llvm::Error::success();
609 
610  return llvm::TypeSwitch<Type, llvm::Error>(baseGEPType)
611  .Case<LLVMStructType>([&](LLVMStructType structType) -> llvm::Error {
612  if (!indices[indexPos].is<IntegerAttr>())
613  return llvm::make_error<GEPStaticIndexError>(indexPos);
614 
615  int32_t gepIndex = indices[indexPos].get<IntegerAttr>().getInt();
616  ArrayRef<Type> elementTypes = structType.getBody();
617  if (gepIndex < 0 ||
618  static_cast<size_t>(gepIndex) >= elementTypes.size())
619  return llvm::make_error<GEPIndexOutOfBoundError>(indexPos);
620 
621  // Instead of recursively going into every children types, we only
622  // dive into the one indexed by gepIndex.
623  return verifyStructIndices(elementTypes[gepIndex], indexPos + 1,
624  indices);
625  })
626  .Case<VectorType, LLVMScalableVectorType, LLVMFixedVectorType,
627  LLVMArrayType>([&](auto containerType) -> llvm::Error {
628  return verifyStructIndices(containerType.getElementType(), indexPos + 1,
629  indices);
630  })
631  .Default(
632  [](auto otherType) -> llvm::Error { return llvm::Error::success(); });
633 }
634 
635 /// Driver function around `recordStructIndices`. Note that we always check
636 /// from the second GEP index since the first one is always dynamic.
637 static llvm::Error verifyStructIndices(Type baseGEPType,
639  return verifyStructIndices(baseGEPType, /*indexPos=*/1, indices);
640 }
641 
644  getOperation(),
645  extractVectorElementType(getType()).cast<LLVMPointerType>(),
646  getElemType())))
647  return failure();
648 
649  if (static_cast<size_t>(
650  llvm::count(getRawConstantIndices(), kDynamicIndex)) !=
651  getDynamicIndices().size())
652  return emitOpError("expected as many dynamic indices as specified in '")
653  << getRawConstantIndicesAttrName().getValue() << "'";
654 
655  if (llvm::Error err =
656  verifyStructIndices(getSourceElementType(), getIndices()))
657  return emitOpError() << llvm::toString(std::move(err));
658 
659  return success();
660 }
661 
662 Type LLVM::GEPOp::getSourceElementType() {
663  if (Optional<Type> elemType = getElemType())
664  return *elemType;
665 
666  return extractVectorElementType(getBase().getType())
667  .cast<LLVMPointerType>()
668  .getElementType();
669 }
670 
671 //===----------------------------------------------------------------------===//
672 // Builder, printer and parser for for LLVM::LoadOp.
673 //===----------------------------------------------------------------------===//
674 
676  Operation *op, StringRef attributeName,
677  llvm::function_ref<LogicalResult(Operation *, SymbolRefAttr)>
678  verifySymbolType) {
679  if (Attribute attribute = op->getAttr(attributeName)) {
680  // The attribute is already verified to be a symbol ref array attribute via
681  // a constraint in the operation definition.
682  for (SymbolRefAttr symbolRef :
683  attribute.cast<ArrayAttr>().getAsRange<SymbolRefAttr>()) {
684  StringAttr metadataName = symbolRef.getRootReference();
685  StringAttr symbolName = symbolRef.getLeafReference();
686  // We want @metadata::@symbol, not just @symbol
687  if (metadataName == symbolName) {
688  return op->emitOpError() << "expected '" << symbolRef
689  << "' to specify a fully qualified reference";
690  }
691  auto metadataOp = SymbolTable::lookupNearestSymbolFrom<LLVM::MetadataOp>(
692  op->getParentOp(), metadataName);
693  if (!metadataOp)
694  return op->emitOpError()
695  << "expected '" << symbolRef << "' to reference a metadata op";
696  Operation *symbolOp =
697  SymbolTable::lookupNearestSymbolFrom(metadataOp, symbolName);
698  if (!symbolOp)
699  return op->emitOpError()
700  << "expected '" << symbolRef << "' to be a valid reference";
701  if (failed(verifySymbolType(symbolOp, symbolRef))) {
702  return failure();
703  }
704  }
705  }
706  return success();
707 }
708 
709 // Verifies that metadata ops are wired up properly.
710 template <typename OpTy>
711 static LogicalResult verifyOpMetadata(Operation *op, StringRef attributeName) {
712  auto verifySymbolType = [op](Operation *symbolOp,
713  SymbolRefAttr symbolRef) -> LogicalResult {
714  if (!isa<OpTy>(symbolOp)) {
715  return op->emitOpError()
716  << "expected '" << symbolRef << "' to resolve to a "
717  << OpTy::getOperationName();
718  }
719  return success();
720  };
721 
722  return verifySymbolAttribute(op, attributeName, verifySymbolType);
723 }
724 
726  // access_groups
727  if (failed(verifyOpMetadata<LLVM::AccessGroupMetadataOp>(
728  op, LLVMDialect::getAccessGroupsAttrName())))
729  return failure();
730 
731  // alias_scopes
732  if (failed(verifyOpMetadata<LLVM::AliasScopeMetadataOp>(
733  op, LLVMDialect::getAliasScopesAttrName())))
734  return failure();
735 
736  // noalias_scopes
737  if (failed(verifyOpMetadata<LLVM::AliasScopeMetadataOp>(
738  op, LLVMDialect::getNoAliasScopesAttrName())))
739  return failure();
740 
741  return success();
742 }
743 
745 
746 void LoadOp::build(OpBuilder &builder, OperationState &result, Type t,
747  Value addr, unsigned alignment, bool isVolatile,
748  bool isNonTemporal) {
749  result.addOperands(addr);
750  result.addTypes(t);
751  if (isVolatile)
752  result.addAttribute(kVolatileAttrName, builder.getUnitAttr());
753  if (isNonTemporal)
754  result.addAttribute(kNonTemporalAttrName, builder.getUnitAttr());
755  if (alignment != 0)
756  result.addAttribute("alignment", builder.getI64IntegerAttr(alignment));
757 }
758 
759 void LoadOp::print(OpAsmPrinter &p) {
760  p << ' ';
761  if (getVolatile_())
762  p << "volatile ";
763  p << getAddr();
764  p.printOptionalAttrDict((*this)->getAttrs(),
765  {kVolatileAttrName, kElemTypeAttrName});
766  p << " : " << getAddr().getType();
767  if (getAddr().getType().cast<LLVMPointerType>().isOpaque())
768  p << " -> " << getType();
769 }
770 
771 // Extract the pointee type from the LLVM pointer type wrapped in MLIR. Return
772 // the resulting type if any, null type if opaque pointers are used, and None
773 // if the given type is not the pointer type.
775  SMLoc trailingTypeLoc) {
776  auto llvmTy = type.dyn_cast<LLVM::LLVMPointerType>();
777  if (!llvmTy) {
778  parser.emitError(trailingTypeLoc, "expected LLVM pointer type");
779  return llvm::None;
780  }
781  return llvmTy.getElementType();
782 }
783 
784 // <operation> ::= `llvm.load` `volatile` ssa-use attribute-dict? `:` type
785 // (`->` type)?
786 ParseResult LoadOp::parse(OpAsmParser &parser, OperationState &result) {
788  Type type;
789  SMLoc trailingTypeLoc;
790 
791  if (succeeded(parser.parseOptionalKeyword("volatile")))
793 
794  if (parser.parseOperand(addr) ||
795  parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
796  parser.getCurrentLocation(&trailingTypeLoc) || parser.parseType(type) ||
797  parser.resolveOperand(addr, type, result.operands))
798  return failure();
799 
800  Optional<Type> elemTy =
801  getLoadStoreElementType(parser, type, trailingTypeLoc);
802  if (!elemTy)
803  return failure();
804  if (*elemTy) {
805  result.addTypes(*elemTy);
806  return success();
807  }
808 
809  Type trailingType;
810  if (parser.parseArrow() || parser.parseType(trailingType))
811  return failure();
812  result.addTypes(trailingType);
813  return success();
814 }
815 
816 //===----------------------------------------------------------------------===//
817 // Builder, printer and parser for LLVM::StoreOp.
818 //===----------------------------------------------------------------------===//
819 
821 
822 void StoreOp::build(OpBuilder &builder, OperationState &result, Value value,
823  Value addr, unsigned alignment, bool isVolatile,
824  bool isNonTemporal) {
825  result.addOperands({value, addr});
826  result.addTypes({});
827  if (isVolatile)
828  result.addAttribute(kVolatileAttrName, builder.getUnitAttr());
829  if (isNonTemporal)
830  result.addAttribute(kNonTemporalAttrName, builder.getUnitAttr());
831  if (alignment != 0)
832  result.addAttribute("alignment", builder.getI64IntegerAttr(alignment));
833 }
834 
835 void StoreOp::print(OpAsmPrinter &p) {
836  p << ' ';
837  if (getVolatile_())
838  p << "volatile ";
839  p << getValue() << ", " << getAddr();
840  p.printOptionalAttrDict((*this)->getAttrs(), {kVolatileAttrName});
841  p << " : ";
842  if (getAddr().getType().cast<LLVMPointerType>().isOpaque())
843  p << getValue().getType() << ", ";
844  p << getAddr().getType();
845 }
846 
847 // <operation> ::= `llvm.store` `volatile` ssa-use `,` ssa-use
848 // attribute-dict? `:` type (`,` type)?
849 ParseResult StoreOp::parse(OpAsmParser &parser, OperationState &result) {
851  Type type;
852  SMLoc trailingTypeLoc;
853 
854  if (succeeded(parser.parseOptionalKeyword("volatile")))
856 
857  if (parser.parseOperand(value) || parser.parseComma() ||
858  parser.parseOperand(addr) ||
859  parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
860  parser.getCurrentLocation(&trailingTypeLoc) || parser.parseType(type))
861  return failure();
862 
863  Type operandType;
864  if (succeeded(parser.parseOptionalComma())) {
865  operandType = type;
866  if (parser.parseType(type))
867  return failure();
868  } else {
869  Optional<Type> maybeOperandType =
870  getLoadStoreElementType(parser, type, trailingTypeLoc);
871  if (!maybeOperandType)
872  return failure();
873  operandType = *maybeOperandType;
874  }
875 
876  if (parser.resolveOperand(value, operandType, result.operands) ||
877  parser.resolveOperand(addr, type, result.operands))
878  return failure();
879 
880  return success();
881 }
882 
883 ///===---------------------------------------------------------------------===//
884 /// LLVM::InvokeOp
885 ///===---------------------------------------------------------------------===//
886 
887 SuccessorOperands InvokeOp::getSuccessorOperands(unsigned index) {
888  assert(index < getNumSuccessors() && "invalid successor index");
889  return SuccessorOperands(index == 0 ? getNormalDestOperandsMutable()
890  : getUnwindDestOperandsMutable());
891 }
892 
893 CallInterfaceCallable InvokeOp::getCallableForCallee() {
894  // Direct call.
895  if (FlatSymbolRefAttr calleeAttr = getCalleeAttr())
896  return calleeAttr;
897  // Indirect call, callee Value is the first operand.
898  return getOperand(0);
899 }
900 
901 Operation::operand_range InvokeOp::getArgOperands() {
902  return getOperands().drop_front(getCallee().has_value() ? 0 : 1);
903 }
904 
906  if (getNumResults() > 1)
907  return emitOpError("must have 0 or 1 result");
908 
909  Block *unwindDest = getUnwindDest();
910  if (unwindDest->empty())
911  return emitError("must have at least one operation in unwind destination");
912 
913  // In unwind destination, first operation must be LandingpadOp
914  if (!isa<LandingpadOp>(unwindDest->front()))
915  return emitError("first operation in unwind destination should be a "
916  "llvm.landingpad operation");
917 
918  return success();
919 }
920 
921 void InvokeOp::print(OpAsmPrinter &p) {
922  auto callee = getCallee();
923  bool isDirect = callee.has_value();
924 
925  p << ' ';
926 
927  // Either function name or pointer
928  if (isDirect)
929  p.printSymbolName(callee.value());
930  else
931  p << getOperand(0);
932 
933  p << '(' << getOperands().drop_front(isDirect ? 0 : 1) << ')';
934  p << " to ";
935  p.printSuccessorAndUseList(getNormalDest(), getNormalDestOperands());
936  p << " unwind ";
937  p.printSuccessorAndUseList(getUnwindDest(), getUnwindDestOperands());
938 
939  p.printOptionalAttrDict((*this)->getAttrs(),
940  {InvokeOp::getOperandSegmentSizeAttr(), "callee"});
941  p << " : ";
942  p.printFunctionalType(llvm::drop_begin(getOperandTypes(), isDirect ? 0 : 1),
943  getResultTypes());
944 }
945 
946 /// <operation> ::= `llvm.invoke` (function-id | ssa-use) `(` ssa-use-list `)`
947 /// `to` bb-id (`[` ssa-use-and-type-list `]`)?
948 /// `unwind` bb-id (`[` ssa-use-and-type-list `]`)?
949 /// attribute-dict? `:` function-type
950 ParseResult InvokeOp::parse(OpAsmParser &parser, OperationState &result) {
952  FunctionType funcType;
953  SymbolRefAttr funcAttr;
954  SMLoc trailingTypeLoc;
955  Block *normalDest, *unwindDest;
956  SmallVector<Value, 4> normalOperands, unwindOperands;
957  Builder &builder = parser.getBuilder();
958 
959  // Parse an operand list that will, in practice, contain 0 or 1 operand. In
960  // case of an indirect call, there will be 1 operand before `(`. In case of a
961  // direct call, there will be no operands and the parser will stop at the
962  // function identifier without complaining.
963  if (parser.parseOperandList(operands))
964  return failure();
965  bool isDirect = operands.empty();
966 
967  // Optionally parse a function identifier.
968  if (isDirect && parser.parseAttribute(funcAttr, "callee", result.attributes))
969  return failure();
970 
971  if (parser.parseOperandList(operands, OpAsmParser::Delimiter::Paren) ||
972  parser.parseKeyword("to") ||
973  parser.parseSuccessorAndUseList(normalDest, normalOperands) ||
974  parser.parseKeyword("unwind") ||
975  parser.parseSuccessorAndUseList(unwindDest, unwindOperands) ||
976  parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
977  parser.getCurrentLocation(&trailingTypeLoc) || parser.parseType(funcType))
978  return failure();
979 
980  if (isDirect) {
981  // Make sure types match.
982  if (parser.resolveOperands(operands, funcType.getInputs(),
983  parser.getNameLoc(), result.operands))
984  return failure();
985  result.addTypes(funcType.getResults());
986  } else {
987  // Construct the LLVM IR Dialect function type that the first operand
988  // should match.
989  if (funcType.getNumResults() > 1)
990  return parser.emitError(trailingTypeLoc,
991  "expected function with 0 or 1 result");
992 
993  Type llvmResultType;
994  if (funcType.getNumResults() == 0) {
995  llvmResultType = LLVM::LLVMVoidType::get(builder.getContext());
996  } else {
997  llvmResultType = funcType.getResult(0);
998  if (!isCompatibleType(llvmResultType))
999  return parser.emitError(trailingTypeLoc,
1000  "expected result to have LLVM type");
1001  }
1002 
1003  SmallVector<Type, 8> argTypes;
1004  argTypes.reserve(funcType.getNumInputs());
1005  for (Type ty : funcType.getInputs()) {
1006  if (isCompatibleType(ty))
1007  argTypes.push_back(ty);
1008  else
1009  return parser.emitError(trailingTypeLoc,
1010  "expected LLVM types as inputs");
1011  }
1012 
1013  auto llvmFuncType = LLVM::LLVMFunctionType::get(llvmResultType, argTypes);
1014  auto wrappedFuncType = LLVM::LLVMPointerType::get(llvmFuncType);
1015 
1016  auto funcArguments = llvm::makeArrayRef(operands).drop_front();
1017 
1018  // Make sure that the first operand (indirect callee) matches the wrapped
1019  // LLVM IR function type, and that the types of the other call operands
1020  // match the types of the function arguments.
1021  if (parser.resolveOperand(operands[0], wrappedFuncType, result.operands) ||
1022  parser.resolveOperands(funcArguments, funcType.getInputs(),
1023  parser.getNameLoc(), result.operands))
1024  return failure();
1025 
1026  result.addTypes(llvmResultType);
1027  }
1028  result.addSuccessors({normalDest, unwindDest});
1029  result.addOperands(normalOperands);
1030  result.addOperands(unwindOperands);
1031 
1032  result.addAttribute(InvokeOp::getOperandSegmentSizeAttr(),
1033  builder.getDenseI32ArrayAttr(
1034  {static_cast<int32_t>(operands.size()),
1035  static_cast<int32_t>(normalOperands.size()),
1036  static_cast<int32_t>(unwindOperands.size())}));
1037  return success();
1038 }
1039 
1040 ///===----------------------------------------------------------------------===//
1041 /// Verifying/Printing/Parsing for LLVM::LandingpadOp.
1042 ///===----------------------------------------------------------------------===//
1043 
1045  Value value;
1046  if (LLVMFuncOp func = (*this)->getParentOfType<LLVMFuncOp>()) {
1047  if (!func.getPersonality())
1048  return emitError(
1049  "llvm.landingpad needs to be in a function with a personality");
1050  }
1051 
1052  if (!getCleanup() && getOperands().empty())
1053  return emitError("landingpad instruction expects at least one clause or "
1054  "cleanup attribute");
1055 
1056  for (unsigned idx = 0, ie = getNumOperands(); idx < ie; idx++) {
1057  value = getOperand(idx);
1058  bool isFilter = value.getType().isa<LLVMArrayType>();
1059  if (isFilter) {
1060  // FIXME: Verify filter clauses when arrays are appropriately handled
1061  } else {
1062  // catch - global addresses only.
1063  // Bitcast ops should have global addresses as their args.
1064  if (auto bcOp = value.getDefiningOp<BitcastOp>()) {
1065  if (auto addrOp = bcOp.getArg().getDefiningOp<AddressOfOp>())
1066  continue;
1067  return emitError("constant clauses expected").attachNote(bcOp.getLoc())
1068  << "global addresses expected as operand to "
1069  "bitcast used in clauses for landingpad";
1070  }
1071  // NullOp and AddressOfOp allowed
1072  if (value.getDefiningOp<NullOp>())
1073  continue;
1074  if (value.getDefiningOp<AddressOfOp>())
1075  continue;
1076  return emitError("clause #")
1077  << idx << " is not a known constant - null, addressof, bitcast";
1078  }
1079  }
1080  return success();
1081 }
1082 
1084  p << (getCleanup() ? " cleanup " : " ");
1085 
1086  // Clauses
1087  for (auto value : getOperands()) {
1088  // Similar to llvm - if clause is an array type then it is filter
1089  // clause else catch clause
1090  bool isArrayTy = value.getType().isa<LLVMArrayType>();
1091  p << '(' << (isArrayTy ? "filter " : "catch ") << value << " : "
1092  << value.getType() << ") ";
1093  }
1094 
1095  p.printOptionalAttrDict((*this)->getAttrs(), {"cleanup"});
1096 
1097  p << ": " << getType();
1098 }
1099 
1100 /// <operation> ::= `llvm.landingpad` `cleanup`?
1101 /// ((`catch` | `filter`) operand-type ssa-use)* attribute-dict?
1102 ParseResult LandingpadOp::parse(OpAsmParser &parser, OperationState &result) {
1103  // Check for cleanup
1104  if (succeeded(parser.parseOptionalKeyword("cleanup")))
1105  result.addAttribute("cleanup", parser.getBuilder().getUnitAttr());
1106 
1107  // Parse clauses with types
1108  while (succeeded(parser.parseOptionalLParen()) &&
1109  (succeeded(parser.parseOptionalKeyword("filter")) ||
1110  succeeded(parser.parseOptionalKeyword("catch")))) {
1112  Type ty;
1113  if (parser.parseOperand(operand) || parser.parseColon() ||
1114  parser.parseType(ty) ||
1115  parser.resolveOperand(operand, ty, result.operands) ||
1116  parser.parseRParen())
1117  return failure();
1118  }
1119 
1120  Type type;
1121  if (parser.parseColon() || parser.parseType(type))
1122  return failure();
1123 
1124  result.addTypes(type);
1125  return success();
1126 }
1127 
1128 //===----------------------------------------------------------------------===//
1129 // CallOp
1130 //===----------------------------------------------------------------------===//
1131 
1132 void CallOp::build(OpBuilder &builder, OperationState &state, TypeRange results,
1133  StringRef callee, ValueRange args) {
1134  build(builder, state, results, builder.getStringAttr(callee), args);
1135 }
1136 
1137 void CallOp::build(OpBuilder &builder, OperationState &state, TypeRange results,
1138  StringAttr callee, ValueRange args) {
1139  build(builder, state, results, SymbolRefAttr::get(callee), args, nullptr);
1140 }
1141 
1142 void CallOp::build(OpBuilder &builder, OperationState &state, LLVMFuncOp func,
1143  ValueRange args) {
1144  SmallVector<Type> results;
1145  Type resultType = func.getFunctionType().getReturnType();
1146  if (!resultType.isa<LLVM::LLVMVoidType>())
1147  results.push_back(resultType);
1148  build(builder, state, results, SymbolRefAttr::get(func), args, nullptr);
1149 }
1150 
1151 CallInterfaceCallable CallOp::getCallableForCallee() {
1152  // Direct call.
1153  if (FlatSymbolRefAttr calleeAttr = getCalleeAttr())
1154  return calleeAttr;
1155  // Indirect call, callee Value is the first operand.
1156  return getOperand(0);
1157 }
1158 
1159 Operation::operand_range CallOp::getArgOperands() {
1160  return getOperands().drop_front(getCallee().has_value() ? 0 : 1);
1161 }
1162 
1163 LogicalResult CallOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
1164  if (getNumResults() > 1)
1165  return emitOpError("must have 0 or 1 result");
1166 
1167  // Type for the callee, we'll get it differently depending if it is a direct
1168  // or indirect call.
1169  Type fnType;
1170 
1171  bool isIndirect = false;
1172 
1173  // If this is an indirect call, the callee attribute is missing.
1174  FlatSymbolRefAttr calleeName = getCalleeAttr();
1175  if (!calleeName) {
1176  isIndirect = true;
1177  if (!getNumOperands())
1178  return emitOpError(
1179  "must have either a `callee` attribute or at least an operand");
1180  auto ptrType = getOperand(0).getType().dyn_cast<LLVMPointerType>();
1181  if (!ptrType)
1182  return emitOpError("indirect call expects a pointer as callee: ")
1183  << ptrType;
1184  fnType = ptrType.getElementType();
1185  } else {
1186  Operation *callee =
1187  symbolTable.lookupNearestSymbolFrom(*this, calleeName.getAttr());
1188  if (!callee)
1189  return emitOpError()
1190  << "'" << calleeName.getValue()
1191  << "' does not reference a symbol in the current scope";
1192  auto fn = dyn_cast<LLVMFuncOp>(callee);
1193  if (!fn)
1194  return emitOpError() << "'" << calleeName.getValue()
1195  << "' does not reference a valid LLVM function";
1196 
1197  fnType = fn.getFunctionType();
1198  }
1199 
1200  LLVMFunctionType funcType = fnType.dyn_cast<LLVMFunctionType>();
1201  if (!funcType)
1202  return emitOpError("callee does not have a functional type: ") << fnType;
1203 
1204  // Verify that the operand and result types match the callee.
1205 
1206  if (!funcType.isVarArg() &&
1207  funcType.getNumParams() != (getNumOperands() - isIndirect))
1208  return emitOpError() << "incorrect number of operands ("
1209  << (getNumOperands() - isIndirect)
1210  << ") for callee (expecting: "
1211  << funcType.getNumParams() << ")";
1212 
1213  if (funcType.getNumParams() > (getNumOperands() - isIndirect))
1214  return emitOpError() << "incorrect number of operands ("
1215  << (getNumOperands() - isIndirect)
1216  << ") for varargs callee (expecting at least: "
1217  << funcType.getNumParams() << ")";
1218 
1219  for (unsigned i = 0, e = funcType.getNumParams(); i != e; ++i)
1220  if (getOperand(i + isIndirect).getType() != funcType.getParamType(i))
1221  return emitOpError() << "operand type mismatch for operand " << i << ": "
1222  << getOperand(i + isIndirect).getType()
1223  << " != " << funcType.getParamType(i);
1224 
1225  if (getNumResults() == 0 &&
1226  !funcType.getReturnType().isa<LLVM::LLVMVoidType>())
1227  return emitOpError() << "expected function call to produce a value";
1228 
1229  if (getNumResults() != 0 &&
1230  funcType.getReturnType().isa<LLVM::LLVMVoidType>())
1231  return emitOpError()
1232  << "calling function with void result must not produce values";
1233 
1234  if (getNumResults() > 1)
1235  return emitOpError()
1236  << "expected LLVM function call to produce 0 or 1 result";
1237 
1238  if (getNumResults() && getResult().getType() != funcType.getReturnType())
1239  return emitOpError() << "result type mismatch: " << getResult().getType()
1240  << " != " << funcType.getReturnType();
1241 
1242  return success();
1243 }
1244 
1245 void CallOp::print(OpAsmPrinter &p) {
1246  auto callee = getCallee();
1247  bool isDirect = callee.has_value();
1248 
1249  // Print the direct callee if present as a function attribute, or an indirect
1250  // callee (first operand) otherwise.
1251  p << ' ';
1252  if (isDirect)
1253  p.printSymbolName(callee.value());
1254  else
1255  p << getOperand(0);
1256 
1257  auto args = getOperands().drop_front(isDirect ? 0 : 1);
1258  p << '(' << args << ')';
1259  p.printOptionalAttrDict(processFMFAttr((*this)->getAttrs()), {"callee"});
1260 
1261  // Reconstruct the function MLIR function type from operand and result types.
1262  p << " : ";
1263  p.printFunctionalType(args.getTypes(), getResultTypes());
1264 }
1265 
1266 // <operation> ::= `llvm.call` (function-id | ssa-use) `(` ssa-use-list `)`
1267 // attribute-dict? `:` function-type
1268 ParseResult CallOp::parse(OpAsmParser &parser, OperationState &result) {
1270  Type type;
1271  SymbolRefAttr funcAttr;
1272  SMLoc trailingTypeLoc;
1273 
1274  // Parse an operand list that will, in practice, contain 0 or 1 operand. In
1275  // case of an indirect call, there will be 1 operand before `(`. In case of a
1276  // direct call, there will be no operands and the parser will stop at the
1277  // function identifier without complaining.
1278  if (parser.parseOperandList(operands))
1279  return failure();
1280  bool isDirect = operands.empty();
1281 
1282  // Optionally parse a function identifier.
1283  if (isDirect)
1284  if (parser.parseAttribute(funcAttr, "callee", result.attributes))
1285  return failure();
1286 
1287  if (parser.parseOperandList(operands, OpAsmParser::Delimiter::Paren) ||
1288  parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
1289  parser.getCurrentLocation(&trailingTypeLoc) || parser.parseType(type))
1290  return failure();
1291 
1292  auto funcType = type.dyn_cast<FunctionType>();
1293  if (!funcType)
1294  return parser.emitError(trailingTypeLoc, "expected function type");
1295  if (funcType.getNumResults() > 1)
1296  return parser.emitError(trailingTypeLoc,
1297  "expected function with 0 or 1 result");
1298  if (isDirect) {
1299  // Make sure types match.
1300  if (parser.resolveOperands(operands, funcType.getInputs(),
1301  parser.getNameLoc(), result.operands))
1302  return failure();
1303  if (funcType.getNumResults() != 0 &&
1304  !funcType.getResult(0).isa<LLVM::LLVMVoidType>())
1305  result.addTypes(funcType.getResults());
1306  } else {
1307  Builder &builder = parser.getBuilder();
1308  Type llvmResultType;
1309  if (funcType.getNumResults() == 0) {
1310  llvmResultType = LLVM::LLVMVoidType::get(builder.getContext());
1311  } else {
1312  llvmResultType = funcType.getResult(0);
1313  if (!isCompatibleType(llvmResultType))
1314  return parser.emitError(trailingTypeLoc,
1315  "expected result to have LLVM type");
1316  }
1317 
1318  SmallVector<Type, 8> argTypes;
1319  argTypes.reserve(funcType.getNumInputs());
1320  for (int i = 0, e = funcType.getNumInputs(); i < e; ++i) {
1321  auto argType = funcType.getInput(i);
1322  if (!isCompatibleType(argType))
1323  return parser.emitError(trailingTypeLoc,
1324  "expected LLVM types as inputs");
1325  argTypes.push_back(argType);
1326  }
1327  auto llvmFuncType = LLVM::LLVMFunctionType::get(llvmResultType, argTypes);
1328  auto wrappedFuncType = LLVM::LLVMPointerType::get(llvmFuncType);
1329 
1330  auto funcArguments =
1331  ArrayRef<OpAsmParser::UnresolvedOperand>(operands).drop_front();
1332 
1333  // Make sure that the first operand (indirect callee) matches the wrapped
1334  // LLVM IR function type, and that the types of the other call operands
1335  // match the types of the function arguments.
1336  if (parser.resolveOperand(operands[0], wrappedFuncType, result.operands) ||
1337  parser.resolveOperands(funcArguments, funcType.getInputs(),
1338  parser.getNameLoc(), result.operands))
1339  return failure();
1340 
1341  if (!llvmResultType.isa<LLVM::LLVMVoidType>())
1342  result.addTypes(llvmResultType);
1343  }
1344 
1345  return success();
1346 }
1347 
1348 //===----------------------------------------------------------------------===//
1349 // ExtractElementOp
1350 //===----------------------------------------------------------------------===//
1351 
1352 /// Expects vector to be an LLVM vector type and position to be an integer type.
1353 void LLVM::ExtractElementOp::build(OpBuilder &b, OperationState &result,
1354  Value vector, Value position,
1355  ArrayRef<NamedAttribute> attrs) {
1356  auto vectorType = vector.getType();
1357  auto llvmType = LLVM::getVectorElementType(vectorType);
1358  build(b, result, llvmType, vector, position);
1359  result.addAttributes(attrs);
1360 }
1361 
1362 //===----------------------------------------------------------------------===//
1363 // ExtractValueOp
1364 //===----------------------------------------------------------------------===//
1365 
1366 /// Extract the type at `position` in the LLVM IR aggregate type
1367 /// `containerType`. Each element of `position` is an index into a nested
1368 /// aggregate type. Return the resulting type or emit an error.
1370  function_ref<InFlightDiagnostic(StringRef)> emitError, Type containerType,
1371  ArrayRef<int64_t> position) {
1372  Type llvmType = containerType;
1373  if (!isCompatibleType(containerType)) {
1374  emitError("expected LLVM IR Dialect type, got ") << containerType;
1375  return {};
1376  }
1377 
1378  // Infer the element type from the structure type: iteratively step inside the
1379  // type by taking the element type, indexed by the position attribute for
1380  // structures. Check the position index before accessing, it is supposed to
1381  // be in bounds.
1382  for (int64_t idx : position) {
1383  if (auto arrayType = llvmType.dyn_cast<LLVMArrayType>()) {
1384  if (idx < 0 || static_cast<unsigned>(idx) >= arrayType.getNumElements()) {
1385  emitError("position out of bounds: ") << idx;
1386  return {};
1387  }
1388  llvmType = arrayType.getElementType();
1389  } else if (auto structType = llvmType.dyn_cast<LLVMStructType>()) {
1390  if (idx < 0 ||
1391  static_cast<unsigned>(idx) >= structType.getBody().size()) {
1392  emitError("position out of bounds: ") << idx;
1393  return {};
1394  }
1395  llvmType = structType.getBody()[idx];
1396  } else {
1397  emitError("expected LLVM IR structure/array type, got: ") << llvmType;
1398  return {};
1399  }
1400  }
1401  return llvmType;
1402 }
1403 
1404 /// Extract the type at `position` in the wrapped LLVM IR aggregate type
1405 /// `containerType`.
1407  ArrayRef<int64_t> position) {
1408  for (int64_t idx : position) {
1409  if (auto structType = llvmType.dyn_cast<LLVMStructType>())
1410  llvmType = structType.getBody()[idx];
1411  else
1412  llvmType = llvmType.cast<LLVMArrayType>().getElementType();
1413  }
1414  return llvmType;
1415 }
1416 
1417 OpFoldResult LLVM::ExtractValueOp::fold(ArrayRef<Attribute> operands) {
1418  auto insertValueOp = getContainer().getDefiningOp<InsertValueOp>();
1419  OpFoldResult result = {};
1420  while (insertValueOp) {
1421  if (getPosition() == insertValueOp.getPosition())
1422  return insertValueOp.getValue();
1423  unsigned min =
1424  std::min(getPosition().size(), insertValueOp.getPosition().size());
1425  // If one is fully prefix of the other, stop propagating back as it will
1426  // miss dependencies. For instance, %3 should not fold to %f0 in the
1427  // following example:
1428  // ```
1429  // %1 = llvm.insertvalue %f0, %0[0, 0] :
1430  // !llvm.array<4 x !llvm.array<4 x f32>>
1431  // %2 = llvm.insertvalue %arr, %1[0] :
1432  // !llvm.array<4 x !llvm.array<4 x f32>>
1433  // %3 = llvm.extractvalue %2[0, 0] : !llvm.array<4 x !llvm.array<4 x f32>>
1434  // ```
1435  if (getPosition().take_front(min) ==
1436  insertValueOp.getPosition().take_front(min))
1437  return result;
1438 
1439  // If neither a prefix, nor the exact position, we can extract out of the
1440  // value being inserted into. Moreover, we can try again if that operand
1441  // is itself an insertvalue expression.
1442  getContainerMutable().assign(insertValueOp.getContainer());
1443  result = getResult();
1444  insertValueOp = insertValueOp.getContainer().getDefiningOp<InsertValueOp>();
1445  }
1446  return result;
1447 }
1448 
1450  auto emitError = [this](StringRef msg) { return emitOpError(msg); };
1452  emitError, getContainer().getType(), getPosition());
1453  if (!valueType)
1454  return failure();
1455 
1456  if (getRes().getType() != valueType)
1457  return emitOpError() << "Type mismatch: extracting from "
1458  << getContainer().getType() << " should produce "
1459  << valueType << " but this op returns "
1460  << getRes().getType();
1461  return success();
1462 }
1463 
1464 void ExtractValueOp::build(OpBuilder &builder, OperationState &state,
1465  Value container, ArrayRef<int64_t> position) {
1466  build(builder, state,
1467  getInsertExtractValueElementType(container.getType(), position),
1468  container, builder.getAttr<DenseI64ArrayAttr>(position));
1469 }
1470 
1471 //===----------------------------------------------------------------------===//
1472 // InsertValueOp
1473 //===----------------------------------------------------------------------===//
1474 
1475 /// Infer the value type from the container type and position.
1476 static ParseResult
1478  Type containerType,
1479  DenseI64ArrayAttr position) {
1481  [&](StringRef msg) {
1482  return parser.emitError(parser.getCurrentLocation(), msg);
1483  },
1484  containerType, position.asArrayRef());
1485  return success(!!valueType);
1486 }
1487 
1488 /// Nothing to print for an inferred type.
1490  Operation *op, Type valueType,
1491  Type containerType,
1492  DenseI64ArrayAttr position) {}
1493 
1495  auto emitError = [this](StringRef msg) { return emitOpError(msg); };
1497  emitError, getContainer().getType(), getPosition());
1498  if (!valueType)
1499  return failure();
1500 
1501  if (getValue().getType() != valueType)
1502  return emitOpError() << "Type mismatch: cannot insert "
1503  << getValue().getType() << " into "
1504  << getContainer().getType();
1505 
1506  return success();
1507 }
1508 
1509 //===----------------------------------------------------------------------===//
1510 // ReturnOp
1511 //===----------------------------------------------------------------------===//
1512 
1514  auto parent = (*this)->getParentOfType<LLVMFuncOp>();
1515  if (!parent)
1516  return success();
1517 
1518  Type expectedType = parent.getFunctionType().getReturnType();
1519  if (expectedType.isa<LLVMVoidType>()) {
1520  if (!getArg())
1521  return success();
1522  InFlightDiagnostic diag = emitOpError("expected no operands");
1523  diag.attachNote(parent->getLoc()) << "when returning from function";
1524  return diag;
1525  }
1526  if (!getArg()) {
1527  if (expectedType.isa<LLVMVoidType>())
1528  return success();
1529  InFlightDiagnostic diag = emitOpError("expected 1 operand");
1530  diag.attachNote(parent->getLoc()) << "when returning from function";
1531  return diag;
1532  }
1533  if (expectedType != getArg().getType()) {
1534  InFlightDiagnostic diag = emitOpError("mismatching result types");
1535  diag.attachNote(parent->getLoc()) << "when returning from function";
1536  return diag;
1537  }
1538  return success();
1539 }
1540 
1541 //===----------------------------------------------------------------------===//
1542 // ResumeOp
1543 //===----------------------------------------------------------------------===//
1544 
1546  if (!getValue().getDefiningOp<LandingpadOp>())
1547  return emitOpError("expects landingpad value as operand");
1548  // No check for personality of function - landingpad op verifies it.
1549  return success();
1550 }
1551 
1552 //===----------------------------------------------------------------------===//
1553 // Verifier for LLVM::AddressOfOp.
1554 //===----------------------------------------------------------------------===//
1555 
1557  Operation *module = op->getParentOp();
1558  while (module && !satisfiesLLVMModule(module))
1559  module = module->getParentOp();
1560  assert(module && "unexpected operation outside of a module");
1561  return module;
1562 }
1563 
1564 GlobalOp AddressOfOp::getGlobal(SymbolTableCollection &symbolTable) {
1565  return dyn_cast_or_null<GlobalOp>(
1566  symbolTable.lookupSymbolIn(parentLLVMModule(*this), getGlobalNameAttr()));
1567 }
1568 
1569 LLVMFuncOp AddressOfOp::getFunction(SymbolTableCollection &symbolTable) {
1570  return dyn_cast_or_null<LLVMFuncOp>(
1571  symbolTable.lookupSymbolIn(parentLLVMModule(*this), getGlobalNameAttr()));
1572 }
1573 
1575 AddressOfOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
1576  Operation *symbol =
1577  symbolTable.lookupSymbolIn(parentLLVMModule(*this), getGlobalNameAttr());
1578 
1579  auto global = dyn_cast_or_null<GlobalOp>(symbol);
1580  auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
1581 
1582  if (!global && !function)
1583  return emitOpError(
1584  "must reference a global defined by 'llvm.mlir.global' or 'llvm.func'");
1585 
1586  LLVMPointerType type = getType();
1587  if (global && global.getAddrSpace() != type.getAddressSpace())
1588  return emitOpError("pointer address space must match address space of the "
1589  "referenced global");
1590 
1591  if (type.isOpaque())
1592  return success();
1593 
1594  if (global && type.getElementType() != global.getType())
1595  return emitOpError(
1596  "the type must be a pointer to the type of the referenced global");
1597 
1598  if (function && type.getElementType() != function.getFunctionType())
1599  return emitOpError(
1600  "the type must be a pointer to the type of the referenced function");
1601 
1602  return success();
1603 }
1604 
1605 //===----------------------------------------------------------------------===//
1606 // Builder, printer and verifier for LLVM::GlobalOp.
1607 //===----------------------------------------------------------------------===//
1608 
1609 void GlobalOp::build(OpBuilder &builder, OperationState &result, Type type,
1610  bool isConstant, Linkage linkage, StringRef name,
1611  Attribute value, uint64_t alignment, unsigned addrSpace,
1612  bool dsoLocal, bool threadLocal,
1613  ArrayRef<NamedAttribute> attrs) {
1614  result.addAttribute(getSymNameAttrName(result.name),
1615  builder.getStringAttr(name));
1616  result.addAttribute(getGlobalTypeAttrName(result.name), TypeAttr::get(type));
1617  if (isConstant)
1618  result.addAttribute(getConstantAttrName(result.name),
1619  builder.getUnitAttr());
1620  if (value)
1621  result.addAttribute(getValueAttrName(result.name), value);
1622  if (dsoLocal)
1623  result.addAttribute(getDsoLocalAttrName(result.name),
1624  builder.getUnitAttr());
1625  if (threadLocal)
1626  result.addAttribute(getThreadLocal_AttrName(result.name),
1627  builder.getUnitAttr());
1628 
1629  // Only add an alignment attribute if the "alignment" input
1630  // is different from 0. The value must also be a power of two, but
1631  // this is tested in GlobalOp::verify, not here.
1632  if (alignment != 0)
1633  result.addAttribute(getAlignmentAttrName(result.name),
1634  builder.getI64IntegerAttr(alignment));
1635 
1636  result.addAttribute(getLinkageAttrName(result.name),
1637  LinkageAttr::get(builder.getContext(), linkage));
1638  if (addrSpace != 0)
1639  result.addAttribute(getAddrSpaceAttrName(result.name),
1640  builder.getI32IntegerAttr(addrSpace));
1641  result.attributes.append(attrs.begin(), attrs.end());
1642  result.addRegion();
1643 }
1644 
1645 void GlobalOp::print(OpAsmPrinter &p) {
1646  p << ' ' << stringifyLinkage(getLinkage()) << ' ';
1647  if (auto unnamedAddr = getUnnamedAddr()) {
1648  StringRef str = stringifyUnnamedAddr(*unnamedAddr);
1649  if (!str.empty())
1650  p << str << ' ';
1651  }
1652  if (getThreadLocal_())
1653  p << "thread_local ";
1654  if (getConstant())
1655  p << "constant ";
1656  p.printSymbolName(getSymName());
1657  p << '(';
1658  if (auto value = getValueOrNull())
1659  p.printAttribute(value);
1660  p << ')';
1661  // Note that the alignment attribute is printed using the
1662  // default syntax here, even though it is an inherent attribute
1663  // (as defined in https://mlir.llvm.org/docs/LangRef/#attributes)
1665  (*this)->getAttrs(),
1666  {SymbolTable::getSymbolAttrName(), getGlobalTypeAttrName(),
1667  getConstantAttrName(), getValueAttrName(), getLinkageAttrName(),
1668  getUnnamedAddrAttrName(), getThreadLocal_AttrName()});
1669 
1670  // Print the trailing type unless it's a string global.
1671  if (getValueOrNull().dyn_cast_or_null<StringAttr>())
1672  return;
1673  p << " : " << getType();
1674 
1675  Region &initializer = getInitializerRegion();
1676  if (!initializer.empty()) {
1677  p << ' ';
1678  p.printRegion(initializer, /*printEntryBlockArgs=*/false);
1679  }
1680 }
1681 
1682 // Parses one of the keywords provided in the list `keywords` and returns the
1683 // position of the parsed keyword in the list. If none of the keywords from the
1684 // list is parsed, returns -1.
1686  ArrayRef<StringRef> keywords) {
1687  for (const auto &en : llvm::enumerate(keywords)) {
1688  if (succeeded(parser.parseOptionalKeyword(en.value())))
1689  return en.index();
1690  }
1691  return -1;
1692 }
1693 
1694 namespace {
1695 template <typename Ty>
1696 struct EnumTraits {};
1697 
1698 #define REGISTER_ENUM_TYPE(Ty) \
1699  template <> \
1700  struct EnumTraits<Ty> { \
1701  static StringRef stringify(Ty value) { return stringify##Ty(value); } \
1702  static unsigned getMaxEnumVal() { return getMaxEnumValFor##Ty(); } \
1703  }
1704 
1705 REGISTER_ENUM_TYPE(Linkage);
1706 REGISTER_ENUM_TYPE(UnnamedAddr);
1707 REGISTER_ENUM_TYPE(CConv);
1708 } // namespace
1709 
1710 /// Parse an enum from the keyword, or default to the provided default value.
1711 /// The return type is the enum type by default, unless overriden with the
1712 /// second template argument.
1713 template <typename EnumTy, typename RetTy = EnumTy>
1715  OperationState &result,
1716  EnumTy defaultValue) {
1718  for (unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
1719  names.push_back(EnumTraits<EnumTy>::stringify(static_cast<EnumTy>(i)));
1720 
1721  int index = parseOptionalKeywordAlternative(parser, names);
1722  if (index == -1)
1723  return static_cast<RetTy>(defaultValue);
1724  return static_cast<RetTy>(index);
1725 }
1726 
1727 // operation ::= `llvm.mlir.global` linkage? `constant`? `@` identifier
1728 // `(` attribute? `)` align? attribute-list? (`:` type)? region?
1729 // align ::= `align` `=` UINT64
1730 //
1731 // The type can be omitted for string attributes, in which case it will be
1732 // inferred from the value of the string as [strlen(value) x i8].
1733 ParseResult GlobalOp::parse(OpAsmParser &parser, OperationState &result) {
1734  MLIRContext *ctx = parser.getContext();
1735  // Parse optional linkage, default to External.
1736  result.addAttribute(getLinkageAttrName(result.name),
1737  LLVM::LinkageAttr::get(
1738  ctx, parseOptionalLLVMKeyword<Linkage>(
1739  parser, result, LLVM::Linkage::External)));
1740 
1741  if (succeeded(parser.parseOptionalKeyword("thread_local")))
1742  result.addAttribute(getThreadLocal_AttrName(result.name),
1743  parser.getBuilder().getUnitAttr());
1744 
1745  // Parse optional UnnamedAddr, default to None.
1746  result.addAttribute(getUnnamedAddrAttrName(result.name),
1747  parser.getBuilder().getI64IntegerAttr(
1748  parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
1749  parser, result, LLVM::UnnamedAddr::None)));
1750 
1751  if (succeeded(parser.parseOptionalKeyword("constant")))
1752  result.addAttribute(getConstantAttrName(result.name),
1753  parser.getBuilder().getUnitAttr());
1754 
1755  StringAttr name;
1756  if (parser.parseSymbolName(name, getSymNameAttrName(result.name),
1757  result.attributes) ||
1758  parser.parseLParen())
1759  return failure();
1760 
1761  Attribute value;
1762  if (parser.parseOptionalRParen()) {
1763  if (parser.parseAttribute(value, getValueAttrName(result.name),
1764  result.attributes) ||
1765  parser.parseRParen())
1766  return failure();
1767  }
1768 
1769  SmallVector<Type, 1> types;
1770  if (parser.parseOptionalAttrDict(result.attributes) ||
1771  parser.parseOptionalColonTypeList(types))
1772  return failure();
1773 
1774  if (types.size() > 1)
1775  return parser.emitError(parser.getNameLoc(), "expected zero or one type");
1776 
1777  Region &initRegion = *result.addRegion();
1778  if (types.empty()) {
1779  if (auto strAttr = value.dyn_cast_or_null<StringAttr>()) {
1780  MLIRContext *context = parser.getContext();
1781  auto arrayType = LLVM::LLVMArrayType::get(IntegerType::get(context, 8),
1782  strAttr.getValue().size());
1783  types.push_back(arrayType);
1784  } else {
1785  return parser.emitError(parser.getNameLoc(),
1786  "type can only be omitted for string globals");
1787  }
1788  } else {
1789  OptionalParseResult parseResult =
1790  parser.parseOptionalRegion(initRegion, /*arguments=*/{},
1791  /*argTypes=*/{});
1792  if (parseResult.has_value() && failed(*parseResult))
1793  return failure();
1794  }
1795 
1796  result.addAttribute(getGlobalTypeAttrName(result.name),
1797  TypeAttr::get(types[0]));
1798  return success();
1799 }
1800 
1802  if (auto intValue = value.dyn_cast<IntegerAttr>())
1803  return intValue.getValue().isNullValue();
1804  if (auto fpValue = value.dyn_cast<FloatAttr>())
1805  return fpValue.getValue().isZero();
1806  if (auto splatValue = value.dyn_cast<SplatElementsAttr>())
1807  return isZeroAttribute(splatValue.getSplatValue<Attribute>());
1808  if (auto elementsValue = value.dyn_cast<ElementsAttr>())
1809  return llvm::all_of(elementsValue.getValues<Attribute>(), isZeroAttribute);
1810  if (auto arrayValue = value.dyn_cast<ArrayAttr>())
1811  return llvm::all_of(arrayValue.getValue(), isZeroAttribute);
1812  return false;
1813 }
1814 
1816  if (!LLVMPointerType::isValidElementType(getType()))
1817  return emitOpError(
1818  "expects type to be a valid element type for an LLVM pointer");
1819  if ((*this)->getParentOp() && !satisfiesLLVMModule((*this)->getParentOp()))
1820  return emitOpError("must appear at the module level");
1821 
1822  if (auto strAttr = getValueOrNull().dyn_cast_or_null<StringAttr>()) {
1823  auto type = getType().dyn_cast<LLVMArrayType>();
1824  IntegerType elementType =
1825  type ? type.getElementType().dyn_cast<IntegerType>() : nullptr;
1826  if (!elementType || elementType.getWidth() != 8 ||
1827  type.getNumElements() != strAttr.getValue().size())
1828  return emitOpError(
1829  "requires an i8 array type of the length equal to that of the string "
1830  "attribute");
1831  }
1832 
1833  if (getLinkage() == Linkage::Common) {
1834  if (Attribute value = getValueOrNull()) {
1835  if (!isZeroAttribute(value)) {
1836  return emitOpError()
1837  << "expected zero value for '"
1838  << stringifyLinkage(Linkage::Common) << "' linkage";
1839  }
1840  }
1841  }
1842 
1843  if (getLinkage() == Linkage::Appending) {
1844  if (!getType().isa<LLVMArrayType>()) {
1845  return emitOpError() << "expected array type for '"
1846  << stringifyLinkage(Linkage::Appending)
1847  << "' linkage";
1848  }
1849  }
1850 
1851  Optional<uint64_t> alignAttr = getAlignment();
1852  if (alignAttr.has_value()) {
1853  uint64_t value = alignAttr.value();
1854  if (!llvm::isPowerOf2_64(value))
1855  return emitError() << "alignment attribute is not a power of 2";
1856  }
1857 
1858  return success();
1859 }
1860 
1861 LogicalResult GlobalOp::verifyRegions() {
1862  if (Block *b = getInitializerBlock()) {
1863  ReturnOp ret = cast<ReturnOp>(b->getTerminator());
1864  if (ret.operand_type_begin() == ret.operand_type_end())
1865  return emitOpError("initializer region cannot return void");
1866  if (*ret.operand_type_begin() != getType())
1867  return emitOpError("initializer region type ")
1868  << *ret.operand_type_begin() << " does not match global type "
1869  << getType();
1870 
1871  for (Operation &op : *b) {
1872  auto iface = dyn_cast<MemoryEffectOpInterface>(op);
1873  if (!iface || !iface.hasNoEffect())
1874  return op.emitError()
1875  << "ops with side effects not allowed in global initializers";
1876  }
1877 
1878  if (getValueOrNull())
1879  return emitOpError("cannot have both initializer value and region");
1880  }
1881 
1882  return success();
1883 }
1884 
1885 //===----------------------------------------------------------------------===//
1886 // LLVM::GlobalCtorsOp
1887 //===----------------------------------------------------------------------===//
1888 
1890 GlobalCtorsOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
1891  for (Attribute ctor : getCtors()) {
1892  if (failed(verifySymbolAttrUse(ctor.cast<FlatSymbolRefAttr>(), *this,
1893  symbolTable)))
1894  return failure();
1895  }
1896  return success();
1897 }
1898 
1900  if (getCtors().size() != getPriorities().size())
1901  return emitError(
1902  "mismatch between the number of ctors and the number of priorities");
1903  return success();
1904 }
1905 
1906 //===----------------------------------------------------------------------===//
1907 // LLVM::GlobalDtorsOp
1908 //===----------------------------------------------------------------------===//
1909 
1911 GlobalDtorsOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
1912  for (Attribute dtor : getDtors()) {
1913  if (failed(verifySymbolAttrUse(dtor.cast<FlatSymbolRefAttr>(), *this,
1914  symbolTable)))
1915  return failure();
1916  }
1917  return success();
1918 }
1919 
1921  if (getDtors().size() != getPriorities().size())
1922  return emitError(
1923  "mismatch between the number of dtors and the number of priorities");
1924  return success();
1925 }
1926 
1927 //===----------------------------------------------------------------------===//
1928 // ShuffleVectorOp
1929 //===----------------------------------------------------------------------===//
1930 
1931 void ShuffleVectorOp::build(OpBuilder &builder, OperationState &state, Value v1,
1932  Value v2, DenseI32ArrayAttr mask,
1933  ArrayRef<NamedAttribute> attrs) {
1934  auto containerType = v1.getType();
1935  auto vType = LLVM::getVectorType(LLVM::getVectorElementType(containerType),
1936  mask.size(),
1937  LLVM::isScalableVectorType(containerType));
1938  build(builder, state, vType, v1, v2, mask);
1939  state.addAttributes(attrs);
1940 }
1941 
1942 void ShuffleVectorOp::build(OpBuilder &builder, OperationState &state, Value v1,
1943  Value v2, ArrayRef<int32_t> mask) {
1944  build(builder, state, v1, v2, builder.getDenseI32ArrayAttr(mask));
1945 }
1946 
1947 /// Build the result type of a shuffle vector operation.
1949  Type &resType, DenseI32ArrayAttr mask) {
1950  if (!LLVM::isCompatibleVectorType(v1Type))
1951  return parser.emitError(parser.getCurrentLocation(),
1952  "expected an LLVM compatible vector type");
1953  resType = LLVM::getVectorType(LLVM::getVectorElementType(v1Type), mask.size(),
1954  LLVM::isScalableVectorType(v1Type));
1955  return success();
1956 }
1957 
1958 /// Nothing to do when the result type is inferred.
1959 static void printShuffleType(AsmPrinter &printer, Operation *op, Type v1Type,
1960  Type resType, DenseI32ArrayAttr mask) {}
1961 
1963  if (LLVM::isScalableVectorType(getV1().getType()) &&
1964  llvm::any_of(getMask(), [](int32_t v) { return v != 0; }))
1965  return emitOpError("expected a splat operation for scalable vectors");
1966  return success();
1967 }
1968 
1969 //===----------------------------------------------------------------------===//
1970 // Implementations for LLVM::LLVMFuncOp.
1971 //===----------------------------------------------------------------------===//
1972 
1973 // Add the entry block to the function.
1974 Block *LLVMFuncOp::addEntryBlock() {
1975  assert(empty() && "function already has an entry block");
1976 
1977  auto *entry = new Block;
1978  push_back(entry);
1979 
1980  // FIXME: Allow passing in proper locations for the entry arguments.
1981  LLVMFunctionType type = getFunctionType();
1982  for (unsigned i = 0, e = type.getNumParams(); i < e; ++i)
1983  entry->addArgument(type.getParamType(i), getLoc());
1984  return entry;
1985 }
1986 
1987 void LLVMFuncOp::build(OpBuilder &builder, OperationState &result,
1988  StringRef name, Type type, LLVM::Linkage linkage,
1989  bool dsoLocal, CConv cconv,
1991  ArrayRef<DictionaryAttr> argAttrs) {
1992  result.addRegion();
1994  builder.getStringAttr(name));
1995  result.addAttribute(getFunctionTypeAttrName(result.name),
1996  TypeAttr::get(type));
1997  result.addAttribute(getLinkageAttrName(result.name),
1998  LinkageAttr::get(builder.getContext(), linkage));
1999  result.addAttribute(getCConvAttrName(result.name),
2000  CConvAttr::get(builder.getContext(), cconv));
2001  result.attributes.append(attrs.begin(), attrs.end());
2002  if (dsoLocal)
2003  result.addAttribute("dso_local", builder.getUnitAttr());
2004  if (argAttrs.empty())
2005  return;
2006 
2007  assert(type.cast<LLVMFunctionType>().getNumParams() == argAttrs.size() &&
2008  "expected as many argument attribute lists as arguments");
2009  function_interface_impl::addArgAndResultAttrs(builder, result, argAttrs,
2010  /*resultAttrs=*/llvm::None);
2011 }
2012 
2013 // Builds an LLVM function type from the given lists of input and output types.
2014 // Returns a null type if any of the types provided are non-LLVM types, or if
2015 // there is more than one output type.
2016 static Type
2018  ArrayRef<Type> outputs,
2020  Builder &b = parser.getBuilder();
2021  if (outputs.size() > 1) {
2022  parser.emitError(loc, "failed to construct function type: expected zero or "
2023  "one function result");
2024  return {};
2025  }
2026 
2027  // Convert inputs to LLVM types, exit early on error.
2028  SmallVector<Type, 4> llvmInputs;
2029  for (auto t : inputs) {
2030  if (!isCompatibleType(t)) {
2031  parser.emitError(loc, "failed to construct function type: expected LLVM "
2032  "type for function arguments");
2033  return {};
2034  }
2035  llvmInputs.push_back(t);
2036  }
2037 
2038  // No output is denoted as "void" in LLVM type system.
2039  Type llvmOutput =
2040  outputs.empty() ? LLVMVoidType::get(b.getContext()) : outputs.front();
2041  if (!isCompatibleType(llvmOutput)) {
2042  parser.emitError(loc, "failed to construct function type: expected LLVM "
2043  "type for function results")
2044  << llvmOutput;
2045  return {};
2046  }
2047  return LLVMFunctionType::get(llvmOutput, llvmInputs,
2048  variadicFlag.isVariadic());
2049 }
2050 
2051 // Parses an LLVM function.
2052 //
2053 // operation ::= `llvm.func` linkage? cconv? function-signature
2054 // function-attributes?
2055 // function-body
2056 //
2057 ParseResult LLVMFuncOp::parse(OpAsmParser &parser, OperationState &result) {
2058  // Default to external linkage if no keyword is provided.
2059  result.addAttribute(
2060  getLinkageAttrName(result.name),
2061  LinkageAttr::get(parser.getContext(),
2062  parseOptionalLLVMKeyword<Linkage>(
2063  parser, result, LLVM::Linkage::External)));
2064 
2065  // Default to C Calling Convention if no keyword is provided.
2066  result.addAttribute(
2067  getCConvAttrName(result.name),
2068  CConvAttr::get(parser.getContext(), parseOptionalLLVMKeyword<CConv>(
2069  parser, result, LLVM::CConv::C)));
2070 
2071  StringAttr nameAttr;
2073  SmallVector<DictionaryAttr> resultAttrs;
2074  SmallVector<Type> resultTypes;
2075  bool isVariadic;
2076 
2077  auto signatureLocation = parser.getCurrentLocation();
2078  if (parser.parseSymbolName(nameAttr, SymbolTable::getSymbolAttrName(),
2079  result.attributes) ||
2081  parser, /*allowVariadic=*/true, entryArgs, isVariadic, resultTypes,
2082  resultAttrs))
2083  return failure();
2084 
2085  SmallVector<Type> argTypes;
2086  for (auto &arg : entryArgs)
2087  argTypes.push_back(arg.type);
2088  auto type =
2089  buildLLVMFunctionType(parser, signatureLocation, argTypes, resultTypes,
2091  if (!type)
2092  return failure();
2094  TypeAttr::get(type));
2095 
2097  return failure();
2099  entryArgs, resultAttrs);
2100 
2101  auto *body = result.addRegion();
2102  OptionalParseResult parseResult =
2103  parser.parseOptionalRegion(*body, entryArgs);
2104  return failure(parseResult.has_value() && failed(*parseResult));
2105 }
2106 
2107 // Print the LLVMFuncOp. Collects argument and result types and passes them to
2108 // helper functions. Drops "void" result since it cannot be parsed back. Skips
2109 // the external linkage since it is the default value.
2111  p << ' ';
2112  if (getLinkage() != LLVM::Linkage::External)
2113  p << stringifyLinkage(getLinkage()) << ' ';
2114  if (getCConv() != LLVM::CConv::C)
2115  p << stringifyCConv(getCConv()) << ' ';
2116 
2117  p.printSymbolName(getName());
2118 
2119  LLVMFunctionType fnType = getFunctionType();
2120  SmallVector<Type, 8> argTypes;
2121  SmallVector<Type, 1> resTypes;
2122  argTypes.reserve(fnType.getNumParams());
2123  for (unsigned i = 0, e = fnType.getNumParams(); i < e; ++i)
2124  argTypes.push_back(fnType.getParamType(i));
2125 
2126  Type returnType = fnType.getReturnType();
2127  if (!returnType.isa<LLVMVoidType>())
2128  resTypes.push_back(returnType);
2129 
2131  isVarArg(), resTypes);
2133  p, *this, argTypes.size(), resTypes.size(),
2134  {getLinkageAttrName(), getCConvAttrName()});
2135 
2136  // Print the body if this is not an external function.
2137  Region &body = getBody();
2138  if (!body.empty()) {
2139  p << ' ';
2140  p.printRegion(body, /*printEntryBlockArgs=*/false,
2141  /*printBlockTerminators=*/true);
2142  }
2143 }
2144 
2145 // Verifies LLVM- and implementation-specific properties of the LLVM func Op:
2146 // - functions don't have 'common' linkage
2147 // - external functions have 'external' or 'extern_weak' linkage;
2148 // - vararg is (currently) only supported for external functions;
2150  if (getLinkage() == LLVM::Linkage::Common)
2151  return emitOpError() << "functions cannot have '"
2152  << stringifyLinkage(LLVM::Linkage::Common)
2153  << "' linkage";
2154 
2155  if (isExternal()) {
2156  if (getLinkage() != LLVM::Linkage::External &&
2157  getLinkage() != LLVM::Linkage::ExternWeak)
2158  return emitOpError() << "external functions must have '"
2159  << stringifyLinkage(LLVM::Linkage::External)
2160  << "' or '"
2161  << stringifyLinkage(LLVM::Linkage::ExternWeak)
2162  << "' linkage";
2163  return success();
2164  }
2165 
2166  return success();
2167 }
2168 
2169 /// Verifies LLVM- and implementation-specific properties of the LLVM func Op:
2170 /// - entry block arguments are of LLVM types.
2171 LogicalResult LLVMFuncOp::verifyRegions() {
2172  if (isExternal())
2173  return success();
2174 
2175  unsigned numArguments = getFunctionType().getNumParams();
2176  Block &entryBlock = front();
2177  for (unsigned i = 0; i < numArguments; ++i) {
2178  Type argType = entryBlock.getArgument(i).getType();
2179  if (!isCompatibleType(argType))
2180  return emitOpError("entry block argument #")
2181  << i << " is not of LLVM type";
2182  }
2183 
2184  return success();
2185 }
2186 
2187 //===----------------------------------------------------------------------===//
2188 // Verification for LLVM::ConstantOp.
2189 //===----------------------------------------------------------------------===//
2190 
2192  if (StringAttr sAttr = getValue().dyn_cast<StringAttr>()) {
2193  auto arrayType = getType().dyn_cast<LLVMArrayType>();
2194  if (!arrayType || arrayType.getNumElements() != sAttr.getValue().size() ||
2195  !arrayType.getElementType().isInteger(8)) {
2196  return emitOpError() << "expected array type of "
2197  << sAttr.getValue().size()
2198  << " i8 elements for the string constant";
2199  }
2200  return success();
2201  }
2202  if (auto structType = getType().dyn_cast<LLVMStructType>()) {
2203  if (structType.getBody().size() != 2 ||
2204  structType.getBody()[0] != structType.getBody()[1]) {
2205  return emitError() << "expected struct type with two elements of the "
2206  "same type, the type of a complex constant";
2207  }
2208 
2209  auto arrayAttr = getValue().dyn_cast<ArrayAttr>();
2210  if (!arrayAttr || arrayAttr.size() != 2) {
2211  return emitOpError() << "expected array attribute with two elements, "
2212  "representing a complex constant";
2213  }
2214  auto re = arrayAttr[0].dyn_cast<TypedAttr>();
2215  auto im = arrayAttr[1].dyn_cast<TypedAttr>();
2216  if (!re || !im || re.getType() != im.getType()) {
2217  return emitOpError()
2218  << "expected array attribute with two elements of the same type";
2219  }
2220 
2221  Type elementType = structType.getBody()[0];
2222  if (!elementType
2223  .isa<IntegerType, Float16Type, Float32Type, Float64Type>()) {
2224  return emitError()
2225  << "expected struct element types to be floating point type or "
2226  "integer type";
2227  }
2228  return success();
2229  }
2230  if (!getValue().isa<IntegerAttr, ArrayAttr, FloatAttr, ElementsAttr>())
2231  return emitOpError()
2232  << "only supports integer, float, string or elements attributes";
2233  return success();
2234 }
2235 
2236 // Constant op constant-folds to its value.
2237 OpFoldResult LLVM::ConstantOp::fold(ArrayRef<Attribute>) { return getValue(); }
2238 
2239 //===----------------------------------------------------------------------===//
2240 // Utility functions for parsing atomic ops
2241 //===----------------------------------------------------------------------===//
2242 
2243 // Helper function to parse a keyword into the specified attribute named by
2244 // `attrName`. The keyword must match one of the string values defined by the
2245 // AtomicBinOp enum. The resulting I64 attribute is added to the `result`
2246 // state.
2248  StringRef attrName) {
2249  SMLoc loc;
2250  StringRef keyword;
2251  if (parser.getCurrentLocation(&loc) || parser.parseKeyword(&keyword))
2252  return failure();
2253 
2254  // Replace the keyword `keyword` with an integer attribute.
2255  auto kind = symbolizeAtomicBinOp(keyword);
2256  if (!kind) {
2257  return parser.emitError(loc)
2258  << "'" << keyword << "' is an incorrect value of the '" << attrName
2259  << "' attribute";
2260  }
2261 
2262  auto value = static_cast<int64_t>(*kind);
2263  auto attr = parser.getBuilder().getI64IntegerAttr(value);
2264  result.addAttribute(attrName, attr);
2265 
2266  return success();
2267 }
2268 
2269 // Helper function to parse a keyword into the specified attribute named by
2270 // `attrName`. The keyword must match one of the string values defined by the
2271 // AtomicOrdering enum. The resulting I64 attribute is added to the `result`
2272 // state.
2274  OperationState &result,
2275  StringRef attrName) {
2276  SMLoc loc;
2277  StringRef ordering;
2278  if (parser.getCurrentLocation(&loc) || parser.parseKeyword(&ordering))
2279  return failure();
2280 
2281  // Replace the keyword `ordering` with an integer attribute.
2282  auto kind = symbolizeAtomicOrdering(ordering);
2283  if (!kind) {
2284  return parser.emitError(loc)
2285  << "'" << ordering << "' is an incorrect value of the '" << attrName
2286  << "' attribute";
2287  }
2288 
2289  auto value = static_cast<int64_t>(*kind);
2290  auto attr = parser.getBuilder().getI64IntegerAttr(value);
2291  result.addAttribute(attrName, attr);
2292 
2293  return success();
2294 }
2295 
2296 //===----------------------------------------------------------------------===//
2297 // Printer, parser and verifier for LLVM::AtomicRMWOp.
2298 //===----------------------------------------------------------------------===//
2299 
2301  p << ' ' << stringifyAtomicBinOp(getBinOp()) << ' ' << getPtr() << ", "
2302  << getVal() << ' ' << stringifyAtomicOrdering(getOrdering()) << ' ';
2303  p.printOptionalAttrDict((*this)->getAttrs(), {"bin_op", "ordering"});
2304  p << " : " << getRes().getType();
2305 }
2306 
2307 // <operation> ::= `llvm.atomicrmw` keyword ssa-use `,` ssa-use keyword
2308 // attribute-dict? `:` type
2309 ParseResult AtomicRMWOp::parse(OpAsmParser &parser, OperationState &result) {
2310  Type type;
2312  if (parseAtomicBinOp(parser, result, "bin_op") || parser.parseOperand(ptr) ||
2313  parser.parseComma() || parser.parseOperand(val) ||
2314  parseAtomicOrdering(parser, result, "ordering") ||
2315  parser.parseOptionalAttrDict(result.attributes) ||
2316  parser.parseColonType(type) ||
2317  parser.resolveOperand(ptr, LLVM::LLVMPointerType::get(type),
2318  result.operands) ||
2319  parser.resolveOperand(val, type, result.operands))
2320  return failure();
2321 
2322  result.addTypes(type);
2323  return success();
2324 }
2325 
2327  auto ptrType = getPtr().getType().cast<LLVM::LLVMPointerType>();
2328  auto valType = getVal().getType();
2329  if (valType != ptrType.getElementType())
2330  return emitOpError("expected LLVM IR element type for operand #0 to "
2331  "match type for operand #1");
2332  auto resType = getRes().getType();
2333  if (resType != valType)
2334  return emitOpError(
2335  "expected LLVM IR result type to match type for operand #1");
2336  if (getBinOp() == AtomicBinOp::fadd || getBinOp() == AtomicBinOp::fsub) {
2338  return emitOpError("expected LLVM IR floating point type");
2339  } else if (getBinOp() == AtomicBinOp::xchg) {
2340  auto intType = valType.dyn_cast<IntegerType>();
2341  unsigned intBitWidth = intType ? intType.getWidth() : 0;
2342  if (intBitWidth != 8 && intBitWidth != 16 && intBitWidth != 32 &&
2343  intBitWidth != 64 && !valType.isa<BFloat16Type>() &&
2344  !valType.isa<Float16Type>() && !valType.isa<Float32Type>() &&
2345  !valType.isa<Float64Type>())
2346  return emitOpError("unexpected LLVM IR type for 'xchg' bin_op");
2347  } else {
2348  auto intType = valType.dyn_cast<IntegerType>();
2349  unsigned intBitWidth = intType ? intType.getWidth() : 0;
2350  if (intBitWidth != 8 && intBitWidth != 16 && intBitWidth != 32 &&
2351  intBitWidth != 64)
2352  return emitOpError("expected LLVM IR integer type");
2353  }
2354 
2355  if (static_cast<unsigned>(getOrdering()) <
2356  static_cast<unsigned>(AtomicOrdering::monotonic))
2357  return emitOpError() << "expected at least '"
2358  << stringifyAtomicOrdering(AtomicOrdering::monotonic)
2359  << "' ordering";
2360 
2361  return success();
2362 }
2363 
2364 //===----------------------------------------------------------------------===//
2365 // Printer, parser and verifier for LLVM::AtomicCmpXchgOp.
2366 //===----------------------------------------------------------------------===//
2367 
2369  p << ' ' << getPtr() << ", " << getCmp() << ", " << getVal() << ' '
2370  << stringifyAtomicOrdering(getSuccessOrdering()) << ' '
2371  << stringifyAtomicOrdering(getFailureOrdering());
2372  p.printOptionalAttrDict((*this)->getAttrs(),
2373  {"success_ordering", "failure_ordering"});
2374  p << " : " << getVal().getType();
2375 }
2376 
2377 // <operation> ::= `llvm.cmpxchg` ssa-use `,` ssa-use `,` ssa-use
2378 // keyword keyword attribute-dict? `:` type
2379 ParseResult AtomicCmpXchgOp::parse(OpAsmParser &parser,
2380  OperationState &result) {
2381  auto &builder = parser.getBuilder();
2382  Type type;
2383  OpAsmParser::UnresolvedOperand ptr, cmp, val;
2384  if (parser.parseOperand(ptr) || parser.parseComma() ||
2385  parser.parseOperand(cmp) || parser.parseComma() ||
2386  parser.parseOperand(val) ||
2387  parseAtomicOrdering(parser, result, "success_ordering") ||
2388  parseAtomicOrdering(parser, result, "failure_ordering") ||
2389  parser.parseOptionalAttrDict(result.attributes) ||
2390  parser.parseColonType(type) ||
2391  parser.resolveOperand(ptr, LLVM::LLVMPointerType::get(type),
2392  result.operands) ||
2393  parser.resolveOperand(cmp, type, result.operands) ||
2394  parser.resolveOperand(val, type, result.operands))
2395  return failure();
2396 
2397  auto boolType = IntegerType::get(builder.getContext(), 1);
2398  auto resultType =
2399  LLVMStructType::getLiteral(builder.getContext(), {type, boolType});
2400  result.addTypes(resultType);
2401 
2402  return success();
2403 }
2404 
2406  auto ptrType = getPtr().getType().cast<LLVM::LLVMPointerType>();
2407  if (!ptrType)
2408  return emitOpError("expected LLVM IR pointer type for operand #0");
2409  auto cmpType = getCmp().getType();
2410  auto valType = getVal().getType();
2411  if (cmpType != ptrType.getElementType() || cmpType != valType)
2412  return emitOpError("expected LLVM IR element type for operand #0 to "
2413  "match type for all other operands");
2414  auto intType = valType.dyn_cast<IntegerType>();
2415  unsigned intBitWidth = intType ? intType.getWidth() : 0;
2416  if (!valType.isa<LLVMPointerType>() && intBitWidth != 8 &&
2417  intBitWidth != 16 && intBitWidth != 32 && intBitWidth != 64 &&
2418  !valType.isa<BFloat16Type>() && !valType.isa<Float16Type>() &&
2419  !valType.isa<Float32Type>() && !valType.isa<Float64Type>())
2420  return emitOpError("unexpected LLVM IR type");
2421  if (getSuccessOrdering() < AtomicOrdering::monotonic ||
2422  getFailureOrdering() < AtomicOrdering::monotonic)
2423  return emitOpError("ordering must be at least 'monotonic'");
2424  if (getFailureOrdering() == AtomicOrdering::release ||
2425  getFailureOrdering() == AtomicOrdering::acq_rel)
2426  return emitOpError("failure ordering cannot be 'release' or 'acq_rel'");
2427  return success();
2428 }
2429 
2430 //===----------------------------------------------------------------------===//
2431 // Printer, parser and verifier for LLVM::FenceOp.
2432 //===----------------------------------------------------------------------===//
2433 
2434 // <operation> ::= `llvm.fence` (`syncscope(`strAttr`)`)? keyword
2435 // attribute-dict?
2436 ParseResult FenceOp::parse(OpAsmParser &parser, OperationState &result) {
2437  StringAttr sScope;
2438  StringRef syncscopeKeyword = "syncscope";
2439  if (!failed(parser.parseOptionalKeyword(syncscopeKeyword))) {
2440  if (parser.parseLParen() ||
2441  parser.parseAttribute(sScope, syncscopeKeyword, result.attributes) ||
2442  parser.parseRParen())
2443  return failure();
2444  } else {
2445  result.addAttribute(syncscopeKeyword,
2446  parser.getBuilder().getStringAttr(""));
2447  }
2448  if (parseAtomicOrdering(parser, result, "ordering") ||
2449  parser.parseOptionalAttrDict(result.attributes))
2450  return failure();
2451  return success();
2452 }
2453 
2454 void FenceOp::print(OpAsmPrinter &p) {
2455  StringRef syncscopeKeyword = "syncscope";
2456  p << ' ';
2457  if (!(*this)->getAttr(syncscopeKeyword).cast<StringAttr>().getValue().empty())
2458  p << "syncscope(" << (*this)->getAttr(syncscopeKeyword) << ") ";
2459  p << stringifyAtomicOrdering(getOrdering());
2460 }
2461 
2463  if (getOrdering() == AtomicOrdering::not_atomic ||
2464  getOrdering() == AtomicOrdering::unordered ||
2465  getOrdering() == AtomicOrdering::monotonic)
2466  return emitOpError("can be given only acquire, release, acq_rel, "
2467  "and seq_cst orderings");
2468  return success();
2469 }
2470 
2471 //===----------------------------------------------------------------------===//
2472 // Folder for LLVM::BitcastOp
2473 //===----------------------------------------------------------------------===//
2474 
2475 OpFoldResult LLVM::BitcastOp::fold(ArrayRef<Attribute> operands) {
2476  // bitcast(x : T0, T0) -> x
2477  if (getArg().getType() == getType())
2478  return getArg();
2479  // bitcast(bitcast(x : T0, T1), T0) -> x
2480  if (auto prev = getArg().getDefiningOp<BitcastOp>())
2481  if (prev.getArg().getType() == getType())
2482  return prev.getArg();
2483  return {};
2484 }
2485 
2486 //===----------------------------------------------------------------------===//
2487 // Folder for LLVM::AddrSpaceCastOp
2488 //===----------------------------------------------------------------------===//
2489 
2490 OpFoldResult LLVM::AddrSpaceCastOp::fold(ArrayRef<Attribute> operands) {
2491  // addrcast(x : T0, T0) -> x
2492  if (getArg().getType() == getType())
2493  return getArg();
2494  // addrcast(addrcast(x : T0, T1), T0) -> x
2495  if (auto prev = getArg().getDefiningOp<AddrSpaceCastOp>())
2496  if (prev.getArg().getType() == getType())
2497  return prev.getArg();
2498  return {};
2499 }
2500 
2501 //===----------------------------------------------------------------------===//
2502 // Folder for LLVM::GEPOp
2503 //===----------------------------------------------------------------------===//
2504 
2505 OpFoldResult LLVM::GEPOp::fold(ArrayRef<Attribute> operands) {
2506  GEPIndicesAdaptor<ArrayRef<Attribute>> indices(getRawConstantIndicesAttr(),
2507  operands.drop_front());
2508 
2509  // gep %x:T, 0 -> %x
2510  if (getBase().getType() == getType() && indices.size() == 1)
2511  if (auto integer = indices[0].dyn_cast_or_null<IntegerAttr>())
2512  if (integer.getValue().isZero())
2513  return getBase();
2514 
2515  // Canonicalize any dynamic indices of constant value to constant indices.
2516  bool changed = false;
2517  SmallVector<GEPArg> gepArgs;
2518  for (auto &iter : llvm::enumerate(indices)) {
2519  auto integer = iter.value().dyn_cast_or_null<IntegerAttr>();
2520  // Constant indices can only be int32_t, so if integer does not fit we
2521  // are forced to keep it dynamic, despite being a constant.
2522  if (!indices.isDynamicIndex(iter.index()) || !integer ||
2523  !integer.getValue().isSignedIntN(kGEPConstantBitWidth)) {
2524 
2525  PointerUnion<IntegerAttr, Value> existing = getIndices()[iter.index()];
2526  if (Value val = existing.dyn_cast<Value>())
2527  gepArgs.emplace_back(val);
2528  else
2529  gepArgs.emplace_back(existing.get<IntegerAttr>().getInt());
2530 
2531  continue;
2532  }
2533 
2534  changed = true;
2535  gepArgs.emplace_back(integer.getInt());
2536  }
2537  if (changed) {
2538  SmallVector<int32_t> rawConstantIndices;
2539  SmallVector<Value> dynamicIndices;
2540  destructureIndices(getSourceElementType(), gepArgs, rawConstantIndices,
2541  dynamicIndices);
2542 
2543  getDynamicIndicesMutable().assign(dynamicIndices);
2544  setRawConstantIndices(rawConstantIndices);
2545  return Value{*this};
2546  }
2547 
2548  return {};
2549 }
2550 
2551 //===----------------------------------------------------------------------===//
2552 // OpAsmDialectInterface
2553 //===----------------------------------------------------------------------===//
2554 
2555 namespace {
2556 struct LLVMOpAsmDialectInterface : public OpAsmDialectInterface {
2558 
2559  AliasResult getAlias(Attribute attr, raw_ostream &os) const override {
2561  .Case<DIBasicTypeAttr, DICompileUnitAttr, DICompositeTypeAttr,
2562  DIDerivedTypeAttr, DIFileAttr, DILexicalBlockAttr,
2563  DILexicalBlockFileAttr, DILocalVariableAttr, DISubprogramAttr,
2564  DISubroutineTypeAttr>([&](auto attr) {
2565  os << decltype(attr)::getMnemonic();
2566  return AliasResult::OverridableAlias;
2567  })
2568  .Default([](Attribute) { return AliasResult::NoAlias; });
2569  }
2570 };
2571 } // namespace
2572 
2573 //===----------------------------------------------------------------------===//
2574 // LLVMDialect initialization, type parsing, and registration.
2575 //===----------------------------------------------------------------------===//
2576 
2577 void LLVMDialect::initialize() {
2578  registerAttributes();
2579 
2580  // clang-format off
2581  addTypes<LLVMVoidType,
2582  LLVMPPCFP128Type,
2583  LLVMX86MMXType,
2584  LLVMTokenType,
2585  LLVMLabelType,
2586  LLVMMetadataType,
2587  LLVMStructType>();
2588  // clang-format on
2589  registerTypes();
2590 
2591  addOperations<
2592 #define GET_OP_LIST
2593 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
2594  ,
2595 #define GET_OP_LIST
2596 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
2597  >();
2598 
2599  // Support unknown operations because not all LLVM operations are registered.
2600  allowUnknownOperations();
2601  addInterfaces<LLVMOpAsmDialectInterface>();
2602 }
2603 
2604 #define GET_OP_CLASSES
2605 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
2606 
2607 #define GET_OP_CLASSES
2608 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
2609 
2610 LogicalResult LLVMDialect::verifyDataLayoutString(
2611  StringRef descr, llvm::function_ref<void(const Twine &)> reportError) {
2612  llvm::Expected<llvm::DataLayout> maybeDataLayout =
2613  llvm::DataLayout::parse(descr);
2614  if (maybeDataLayout)
2615  return success();
2616 
2617  std::string message;
2618  llvm::raw_string_ostream messageStream(message);
2619  llvm::logAllUnhandledErrors(maybeDataLayout.takeError(), messageStream);
2620  reportError("invalid data layout descriptor: " + messageStream.str());
2621  return failure();
2622 }
2623 
2624 /// Verify LLVM dialect attributes.
2625 LogicalResult LLVMDialect::verifyOperationAttribute(Operation *op,
2626  NamedAttribute attr) {
2627  // If the `llvm.loop` attribute is present, enforce the following structure,
2628  // which the module translation can assume.
2629  if (attr.getName() == LLVMDialect::getLoopAttrName()) {
2630  auto loopAttr = attr.getValue().dyn_cast<DictionaryAttr>();
2631  if (!loopAttr)
2632  return op->emitOpError() << "expected '" << LLVMDialect::getLoopAttrName()
2633  << "' to be a dictionary attribute";
2634  Optional<NamedAttribute> parallelAccessGroup =
2635  loopAttr.getNamed(LLVMDialect::getParallelAccessAttrName());
2636  if (parallelAccessGroup) {
2637  auto accessGroups = parallelAccessGroup->getValue().dyn_cast<ArrayAttr>();
2638  if (!accessGroups)
2639  return op->emitOpError()
2640  << "expected '" << LLVMDialect::getParallelAccessAttrName()
2641  << "' to be an array attribute";
2642  for (Attribute attr : accessGroups) {
2643  auto accessGroupRef = attr.dyn_cast<SymbolRefAttr>();
2644  if (!accessGroupRef)
2645  return op->emitOpError()
2646  << "expected '" << attr << "' to be a symbol reference";
2647  StringAttr metadataName = accessGroupRef.getRootReference();
2648  auto metadataOp =
2649  SymbolTable::lookupNearestSymbolFrom<LLVM::MetadataOp>(
2650  op->getParentOp(), metadataName);
2651  if (!metadataOp)
2652  return op->emitOpError()
2653  << "expected '" << attr << "' to reference a metadata op";
2654  StringAttr accessGroupName = accessGroupRef.getLeafReference();
2655  Operation *accessGroupOp =
2656  SymbolTable::lookupNearestSymbolFrom(metadataOp, accessGroupName);
2657  if (!accessGroupOp)
2658  return op->emitOpError()
2659  << "expected '" << attr << "' to reference an access_group op";
2660  }
2661  }
2662 
2663  Optional<NamedAttribute> loopOptions =
2664  loopAttr.getNamed(LLVMDialect::getLoopOptionsAttrName());
2665  if (loopOptions && !loopOptions->getValue().isa<LoopOptionsAttr>())
2666  return op->emitOpError()
2667  << "expected '" << LLVMDialect::getLoopOptionsAttrName()
2668  << "' to be a `loopopts` attribute";
2669  }
2670 
2671  if (attr.getName() == LLVMDialect::getReadnoneAttrName()) {
2672  const auto attrName = LLVMDialect::getReadnoneAttrName();
2673  if (!isa<FunctionOpInterface>(op))
2674  return op->emitOpError()
2675  << "'" << attrName
2676  << "' is permitted only on FunctionOpInterface operations";
2677  if (!attr.getValue().isa<UnitAttr>())
2678  return op->emitOpError()
2679  << "expected '" << attrName << "' to be a unit attribute";
2680  }
2681 
2682  if (attr.getName() == LLVMDialect::getStructAttrsAttrName()) {
2683  return op->emitOpError()
2684  << "'" << LLVM::LLVMDialect::getStructAttrsAttrName()
2685  << "' is permitted only in argument or result attributes";
2686  }
2687 
2688  // If the data layout attribute is present, it must use the LLVM data layout
2689  // syntax. Try parsing it and report errors in case of failure. Users of this
2690  // attribute may assume it is well-formed and can pass it to the (asserting)
2691  // llvm::DataLayout constructor.
2692  if (attr.getName() != LLVM::LLVMDialect::getDataLayoutAttrName())
2693  return success();
2694  if (auto stringAttr = attr.getValue().dyn_cast<StringAttr>())
2695  return verifyDataLayoutString(
2696  stringAttr.getValue(),
2697  [op](const Twine &message) { op->emitOpError() << message.str(); });
2698 
2699  return op->emitOpError() << "expected '"
2700  << LLVM::LLVMDialect::getDataLayoutAttrName()
2701  << "' to be a string attributes";
2702 }
2703 
2704 LogicalResult LLVMDialect::verifyStructAttr(Operation *op, Attribute attr,
2705  Type annotatedType) {
2706  auto structType = annotatedType.dyn_cast<LLVMStructType>();
2707  if (!structType) {
2708  const auto emitIncorrectAnnotatedType = [&op]() {
2709  return op->emitError()
2710  << "expected '" << LLVMDialect::getStructAttrsAttrName()
2711  << "' to annotate '!llvm.struct' or '!llvm.ptr<struct<...>>'";
2712  };
2713  const auto ptrType = annotatedType.dyn_cast<LLVMPointerType>();
2714  if (!ptrType)
2715  return emitIncorrectAnnotatedType();
2716  structType = ptrType.getElementType().dyn_cast<LLVMStructType>();
2717  if (!structType)
2718  return emitIncorrectAnnotatedType();
2719  }
2720 
2721  const auto arrAttrs = attr.dyn_cast<ArrayAttr>();
2722  if (!arrAttrs)
2723  return op->emitError() << "expected '"
2724  << LLVMDialect::getStructAttrsAttrName()
2725  << "' to be an array attribute";
2726 
2727  if (structType.getBody().size() != arrAttrs.size())
2728  return op->emitError()
2729  << "size of '" << LLVMDialect::getStructAttrsAttrName()
2730  << "' must match the size of the annotated '!llvm.struct'";
2731  return success();
2732 }
2733 
2735  Operation *op, Attribute attr,
2736  const std::function<Type(FunctionOpInterface)> &getAnnotatedType) {
2737  if (auto funcOp = dyn_cast<FunctionOpInterface>(op))
2738  return LLVMDialect::verifyStructAttr(op, attr, getAnnotatedType(funcOp));
2739  return op->emitError() << "expected '"
2740  << LLVMDialect::getStructAttrsAttrName()
2741  << "' to be used on function-like operations";
2742 }
2743 
2744 /// Verify LLVMIR function argument attributes.
2745 LogicalResult LLVMDialect::verifyRegionArgAttribute(Operation *op,
2746  unsigned regionIdx,
2747  unsigned argIdx,
2748  NamedAttribute argAttr) {
2749  // Check that llvm.noalias is a unit attribute.
2750  if (argAttr.getName() == LLVMDialect::getNoAliasAttrName() &&
2751  !argAttr.getValue().isa<UnitAttr>())
2752  return op->emitError()
2753  << "expected llvm.noalias argument attribute to be a unit attribute";
2754  // Check that llvm.align is an integer attribute.
2755  if (argAttr.getName() == LLVMDialect::getAlignAttrName() &&
2756  !argAttr.getValue().isa<IntegerAttr>())
2757  return op->emitError()
2758  << "llvm.align argument attribute of non integer type";
2759  if (argAttr.getName() == LLVMDialect::getStructAttrsAttrName()) {
2761  op, argAttr.getValue(), [argIdx](FunctionOpInterface funcOp) {
2762  return funcOp.getArgumentTypes()[argIdx];
2763  });
2764  }
2765  return success();
2766 }
2767 
2768 LogicalResult LLVMDialect::verifyRegionResultAttribute(Operation *op,
2769  unsigned regionIdx,
2770  unsigned resIdx,
2771  NamedAttribute resAttr) {
2772  StringAttr name = resAttr.getName();
2773  if (name == LLVMDialect::getStructAttrsAttrName()) {
2775  op, resAttr.getValue(), [resIdx](FunctionOpInterface funcOp) {
2776  return funcOp.getResultTypes()[resIdx];
2777  });
2778  }
2779  if (auto funcOp = dyn_cast<FunctionOpInterface>(op)) {
2780  mlir::Type resTy = funcOp.getResultTypes()[resIdx];
2781 
2782  // Check to see if this function has a void return with a result attribute
2783  // to it. It isn't clear what semantics we would assign to that.
2784  if (resTy.isa<LLVMVoidType>())
2785  return op->emitError() << "cannot attach result attributes to functions "
2786  "with a void return";
2787 
2788  // LLVM attribute may be attached to a result of operation
2789  // that has not been converted to LLVM dialect yet, so the result
2790  // may have a type with unknown representation in LLVM dialect type
2791  // space. In this case we cannot verify whether the attribute may be
2792  // attached to a result of such type.
2793  bool verifyValueType = isCompatibleType(resTy);
2794  Attribute attrValue = resAttr.getValue();
2795 
2796  // TODO: get rid of code duplication here and in verifyRegionArgAttribute().
2797  if (name == LLVMDialect::getAlignAttrName()) {
2798  if (!attrValue.isa<IntegerAttr>())
2799  return op->emitError() << "expected llvm.align result attribute to be "
2800  "an integer attribute";
2801  if (verifyValueType && !resTy.isa<LLVMPointerType>())
2802  return op->emitError()
2803  << "llvm.align attribute attached to non-pointer result";
2804  return success();
2805  }
2806  if (name == LLVMDialect::getNoAliasAttrName()) {
2807  if (!attrValue.isa<UnitAttr>())
2808  return op->emitError() << "expected llvm.noalias result attribute to "
2809  "be a unit attribute";
2810  if (verifyValueType && !resTy.isa<LLVMPointerType>())
2811  return op->emitError()
2812  << "llvm.noalias attribute attached to non-pointer result";
2813  return success();
2814  }
2815  if (name == LLVMDialect::getNoUndefAttrName()) {
2816  if (!attrValue.isa<UnitAttr>())
2817  return op->emitError() << "expected llvm.noundef result attribute to "
2818  "be a unit attribute";
2819  return success();
2820  }
2821  if (name == LLVMDialect::getSExtAttrName()) {
2822  if (!attrValue.isa<UnitAttr>())
2823  return op->emitError() << "expected llvm.signext result attribute to "
2824  "be a unit attribute";
2825  if (verifyValueType && !resTy.isa<mlir::IntegerType>())
2826  return op->emitError()
2827  << "llvm.signext attribute attached to non-integer result";
2828  return success();
2829  }
2830  if (name == LLVMDialect::getZExtAttrName()) {
2831  if (!attrValue.isa<UnitAttr>())
2832  return op->emitError() << "expected llvm.zeroext result attribute to "
2833  "be a unit attribute";
2834  if (verifyValueType && !resTy.isa<mlir::IntegerType>())
2835  return op->emitError()
2836  << "llvm.zeroext attribute attached to non-integer result";
2837  return success();
2838  }
2839  }
2840 
2841  return success();
2842 }
2843 
2844 //===----------------------------------------------------------------------===//
2845 // Utility functions.
2846 //===----------------------------------------------------------------------===//
2847 
2849  StringRef name, StringRef value,
2850  LLVM::Linkage linkage) {
2851  assert(builder.getInsertionBlock() &&
2852  builder.getInsertionBlock()->getParentOp() &&
2853  "expected builder to point to a block constrained in an op");
2854  auto module =
2855  builder.getInsertionBlock()->getParentOp()->getParentOfType<ModuleOp>();
2856  assert(module && "builder points to an op outside of a module");
2857 
2858  // Create the global at the entry of the module.
2859  OpBuilder moduleBuilder(module.getBodyRegion(), builder.getListener());
2860  MLIRContext *ctx = builder.getContext();
2861  auto type = LLVM::LLVMArrayType::get(IntegerType::get(ctx, 8), value.size());
2862  auto global = moduleBuilder.create<LLVM::GlobalOp>(
2863  loc, type, /*isConstant=*/true, linkage, name,
2864  builder.getStringAttr(value), /*alignment=*/0);
2865 
2866  // Get the pointer to the first character in the global string.
2867  Value globalPtr = builder.create<LLVM::AddressOfOp>(loc, global);
2868  return builder.create<LLVM::GEPOp>(
2869  loc, LLVM::LLVMPointerType::get(IntegerType::get(ctx, 8)), globalPtr,
2870  ArrayRef<GEPArg>{0, 0});
2871 }
2872 
2874  return op->hasTrait<OpTrait::SymbolTable>() &&
2876 }
static std::string toString(bytecode::Section::ID sectionID)
Stringify the given section ID.
static std::string diag(llvm::Value &value)
static constexpr const bool value
static int parseOptionalKeywordAlternative(OpAsmParser &parser, ArrayRef< StringRef > keywords)
static ParseResult parseGEPIndices(OpAsmParser &parser, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &indices, DenseI32ArrayAttr &rawConstantIndices)
static void printSwitchOpCases(OpAsmPrinter &p, SwitchOp op, Type flagType, ElementsAttr caseValues, SuccessorRange caseDestinations, OperandRangeRange caseOperands, const TypeRangeRange &caseOperandTypes)
static ParseResult parseCmpOp(OpAsmParser &parser, OperationState &result)
static ParseResult parseSwitchOpCases(OpAsmParser &parser, Type flagType, ElementsAttr &caseValues, SmallVectorImpl< Block * > &caseDestinations, SmallVectorImpl< SmallVector< OpAsmParser::UnresolvedOperand >> &caseOperands, SmallVectorImpl< SmallVector< Type >> &caseOperandTypes)
<cases> ::= integer : bb-id (( ssa-use-and-type-list ))? ( , integer : bb-id (( ssa-use-and-type-list...
static LogicalResult verifyOpaquePtr(Operation *op, LLVMPointerType ptrType, Optional< Type > ptrElementType)
Checks that the elemental type is present in either the pointer type or the attribute,...
static ParseResult parseLLVMOpAttrs(OpAsmParser &parser, NamedAttrList &result)
Definition: LLVMDialect.cpp:63
static RetTy parseOptionalLLVMKeyword(OpAsmParser &parser, OperationState &result, EnumTy defaultValue)
Parse an enum from the keyword, or default to the provided default value.
static LogicalResult verifyMemoryOpMetadata(Operation *op)
static bool isZeroAttribute(Attribute value)
static constexpr const char kVolatileAttrName[]
Definition: LLVMDialect.cpp:44
static void printGEPIndices(OpAsmPrinter &printer, LLVM::GEPOp gepOp, OperandRange indices, DenseI32ArrayAttr rawConstantIndices)
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:50
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 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:75
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 Optional< Type > getLoadStoreElementType(OpAsmParser &parser, Type type, SMLoc trailingTypeLoc)
static Type getI1SameShape(Type type)
Returns a boolean type that has the same shape as type.
Definition: LLVMDialect.cpp:91
static LogicalResult verifyOpMetadata(Operation *op, StringRef attributeName)
static ParseResult parseShuffleType(AsmParser &parser, Type v1Type, Type &resType, DenseI32ArrayAttr mask)
Build the result type of a shuffle vector operation.
LogicalResult verifySymbolAttribute(Operation *op, StringRef attributeName, llvm::function_ref< LogicalResult(Operation *, SymbolRefAttr)> verifySymbolType)
static constexpr const char kElemTypeAttrName[]
Definition: LLVMDialect.cpp:46
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:68
static LogicalResult verifyFuncOpInterfaceStructAttr(Operation *op, Attribute attr, const std::function< Type(FunctionOpInterface)> &getAnnotatedType)
static ParseResult parseAtomicOrdering(OpAsmParser &parser, OperationState &result, StringRef attrName)
static void printInsertExtractValueElementType(AsmPrinter &printer, Operation *op, Type valueType, Type containerType, DenseI64ArrayAttr position)
Nothing to print for an inferred type.
static constexpr const char kNonTemporalAttrName[]
Definition: LLVMDialect.cpp:45
static ParseResult parseAtomicBinOp(OpAsmParser &parser, OperationState &result, StringRef attrName)
#define REGISTER_ENUM_TYPE(Ty)
@ None
Operation::operand_range getIndices(Operation *op)
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:696
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:67
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 parseOptionalColonTypeList(SmallVectorImpl< Type > &result)=0
Parse an optional colon followed by a type list, which if present must have at least one type.
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 ParseResult parseColonType(Type &result)=0
Parse a colon followed by a type.
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 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
U dyn_cast() const
Definition: Attributes.h:127
bool isa() const
Casting utility functions.
Definition: Attributes.h:117
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:137
BlockArgument getArgument(unsigned i)
Definition: Block.h:118
Operation & front()
Definition: Block.h:142
Operation * getParentOp()
Returns the closest surrounding operation that contains this block.
Definition: Block.cpp:30
This class is a general helper class for creating context-global objects like types,...
Definition: Builders.h:49
UnitAttr getUnitAttr()
Definition: Builders.cpp:99
IntegerAttr getI32IntegerAttr(int32_t value)
Definition: Builders.cpp:190
DenseI32ArrayAttr getDenseI32ArrayAttr(ArrayRef< int32_t > values)
Definition: Builders.cpp:153
IntegerAttr getI64IntegerAttr(int64_t value)
Definition: Builders.cpp:113
StringAttr getStringAttr(const Twine &bytes)
Definition: Builders.cpp:243
MLIRContext * getContext() const
Definition: Builders.h:54
DenseIntElementsAttr getI32VectorAttr(ArrayRef< int32_t > values)
Definition: Builders.cpp:123
Attr getAttr(Args &&...args)
Get or construct an instance of the attribute Attr with provided arguments.
Definition: Builders.h:95
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 diagnostic that is inflight and set to be reported.
Definition: Diagnostics.h:307
Diagnostic & attachNote(Optional< Location > noteLoc=llvm::None)
Attaches a note to this diagnostic.
Definition: Diagnostics.h:345
Class used for building a 'llvm.getelementptr'.
Definition: LLVMDialect.h:74
Class used for convenient access and iteration over GEP indices.
Definition: LLVMDialect.h:114
size_t size() const
Returns the amount of indices of the GEPOp.
Definition: LLVMDialect.h:148
LLVM dialect structure type representing a collection of different-typed elements manipulated togethe...
Definition: LLVMTypes.h:107
ArrayRef< Type > getBody() const
Returns the list of element types contained in a non-opaque struct.
Definition: LLVMTypes.cpp:486
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:64
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:56
NamedAttrList is array of NamedAttributes that tracks whether it is sorted and does some basic work t...
Optional< NamedAttribute > getNamed(StringRef name) const
Return the specified named attribute if present, None 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:150
StringAttr getName() const
Return the name of the attribute.
Definition: Attributes.cpp:32
Attribute getValue() const
Return the value of the attribute.
Definition: Attributes.h:164
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 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:81
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:198
Listener * getListener() const
Returns the current listener of this builder, or nullptr if this builder doesn't have a listener.
Definition: Builders.h:272
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
Definition: Builders.cpp:422
Block * getInsertionBlock() const
Return the block the current insertion point belongs to.
Definition: Builders.h:394
This class represents a single result from folding an operation.
Definition: OpDefinition.h:233
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:341
This class represents a contiguous range of operand ranges, e.g.
Definition: ValueRange.h:81
This class implements the operand iterators for the Operation class.
Definition: ValueRange.h:41
Operation is a basic unit of execution within MLIR.
Definition: Operation.h:31
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
Definition: Operation.h:528
Attribute getAttr(StringAttr name)
Return the specified attribute if present, null otherwise.
Definition: Operation.h:371
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
Definition: Operation.h:165
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
Definition: Operation.cpp:225
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
Definition: Operation.h:169
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
Definition: Operation.cpp:512
This class implements Optional functionality for ParseResult.
Definition: OpDefinition.h:37
ParseResult value() const
Access the internal ParseResult value.
Definition: OpDefinition.h:50
bool has_value() const
Returns true if we contain a valid ParseResult value.
Definition: OpDefinition.h:47
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
bool empty()
Definition: Region.h:60
An attribute that represents a reference to a splat vector or tensor constant, meaning all of the ele...
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:245
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:58
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
U cast() const
Definition: Types.h:280
MLIRContext * getContext() const
Return the MLIRContext in which this type was uniqued.
Definition: Types.cpp:19
bool isa_and_nonnull() const
Definition: Types.h:265
U dyn_cast() const
Definition: Types.h:270
bool isa() const
Definition: Types.h:260
unsigned getIntOrFloatBitWidth() const
Return the bit width of an integer or a float type, assert failure on other types.
Definition: Types.cpp:93
This class provides an abstraction over the different types of ranges over Values.
Definition: ValueRange.h:349
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:85
Type getType() const
Return the type of this value.
Definition: Value.h:114
U dyn_cast() const
Definition: Value.h:95
static DenseArrayAttrImpl get(MLIRContext *context, ArrayRef< int32_t > content)
Builder from ArrayRef<T>.
A named class for passing around the variadic flag.
Value createGlobalString(Location loc, OpBuilder &builder, StringRef name, StringRef value, Linkage linkage)
Create an LLVM global containing the string "value" at the module containing surrounding the insertio...
Type getVectorType(Type elementType, unsigned numElements, bool isScalable=false)
Creates an LLVM dialect-compatible vector type with the given element type and length.
Definition: LLVMTypes.cpp:910
bool isScalableVectorType(Type vectorType)
Returns whether a vector type is scalable or not.
Definition: LLVMTypes.cpp:900
bool isCompatibleVectorType(Type type)
Returns true if the given type is a vector type compatible with the LLVM dialect.
Definition: LLVMTypes.cpp:857
bool satisfiesLLVMModule(Operation *op)
LLVM requires some operations to be inside of a Module operation.
llvm::PointerEmbeddedInt< int32_t, kGEPConstantBitWidth > GEPConstantIndex
Wrapper around a int32_t for use in a PointerUnion.
Definition: LLVMDialect.h:68
constexpr int kGEPConstantBitWidth
Bit-width of a 'GEPConstantIndex' within GEPArg.
Definition: LLVMDialect.h:65
bool isCompatibleType(Type type)
Returns true if the given type is compatible with the LLVM dialect.
Definition: LLVMTypes.cpp:839
bool isCompatibleFloatingPointType(Type type)
Returns true if the given type is a floating-point type compatible with the LLVM dialect.
Definition: LLVMTypes.cpp:852
llvm::ElementCount getVectorNumElements(Type type)
Returns the element count of any LLVM-compatible vector type.
Definition: LLVMTypes.cpp:882
Type getVectorElementType(Type type)
Returns the element type of any vector type compatible with the LLVM dialect.
Definition: LLVMTypes.cpp:873
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
Definition: Matchers.h:230
void printFunctionSignature(OpAsmPrinter &p, Operation *op, ArrayRef< Type > argTypes, bool isVariadic, ArrayRef< Type > resultTypes)
Prints the signature of the function-like operation op.
void printFunctionAttributes(OpAsmPrinter &p, Operation *op, unsigned numInputs, unsigned numResults, ArrayRef< StringRef > elided={})
Prints the list of function prefixed with the "attributes" keyword.
void addArgAndResultAttrs(Builder &builder, OperationState &result, ArrayRef< DictionaryAttr > argAttrs, ArrayRef< DictionaryAttr > resultAttrs)
Adds argument and result attributes, provided as argAttrs and resultAttrs arguments,...
StringRef getTypeAttrName()
Return the name of the attribute used for function types.
ParseResult parseFunctionSignature(OpAsmParser &parser, bool allowVariadic, SmallVectorImpl< OpAsmParser::Argument > &arguments, bool &isVariadic, SmallVectorImpl< Type > &resultTypes, SmallVectorImpl< DictionaryAttr > &resultAttrs)
Parses a function signature using parser.
Type getFunctionType(Builder &builder, ArrayRef< OpAsmParser::Argument > argAttrs, ArrayRef< Type > resultTypes)
Get a function type corresponding to an array of arguments (which have types) and a set of result typ...
Value constantIndex(OpBuilder &builder, Location loc, int64_t i)
Generates a constant of index type.
Definition: CodegenUtils.h:245
std::string stringify(T &&t)
Generically convert a value to a std::string.
Include the generated interface declarations.
bool matchPattern(Value value, const Pattern &pattern)
Entry point for matching a pattern over a Value.
Definition: Matchers.h:329
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:62
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
detail::constant_int_op_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:352
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
Definition: Verifier.cpp:372
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.