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