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