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