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