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