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