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