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