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/DialectImplementation.h"
17 #include "mlir/IR/FunctionImplementation.h"
18 #include "mlir/IR/MLIRContext.h"
19 #include "mlir/IR/Module.h"
20 #include "mlir/IR/StandardTypes.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>(getParentOp(), global_name());
989 }
990 
991 LLVMFuncOp AddressOfOp::getFunction() {
992   return lookupSymbolInModule<LLVM::LLVMFuncOp>(getParentOp(), global_name());
993 }
994 
995 static LogicalResult verify(AddressOfOp op) {
996   auto global = op.getGlobal();
997   auto function = op.getFunction();
998   if (!global && !function)
999     return op.emitOpError(
1000         "must reference a global defined by 'llvm.mlir.global' or 'llvm.func'");
1001 
1002   if (global && global.getType().getPointerTo(global.addr_space()) !=
1003                     op.getResult().getType())
1004     return op.emitOpError(
1005         "the type must be a pointer to the type of the referenced global");
1006 
1007   if (function && function.getType().getPointerTo() != op.getResult().getType())
1008     return op.emitOpError(
1009         "the type must be a pointer to the type of the referenced function");
1010 
1011   return success();
1012 }
1013 
1014 //===----------------------------------------------------------------------===//
1015 // Builder, printer and verifier for LLVM::GlobalOp.
1016 //===----------------------------------------------------------------------===//
1017 
1018 /// Returns the name used for the linkage attribute. This *must* correspond to
1019 /// the name of the attribute in ODS.
1020 static StringRef getLinkageAttrName() { return "linkage"; }
1021 
1022 void GlobalOp::build(OpBuilder &builder, OperationState &result, LLVMType type,
1023                      bool isConstant, Linkage linkage, StringRef name,
1024                      Attribute value, unsigned addrSpace,
1025                      ArrayRef<NamedAttribute> attrs) {
1026   result.addAttribute(SymbolTable::getSymbolAttrName(),
1027                       builder.getStringAttr(name));
1028   result.addAttribute("type", TypeAttr::get(type));
1029   if (isConstant)
1030     result.addAttribute("constant", builder.getUnitAttr());
1031   if (value)
1032     result.addAttribute("value", value);
1033   result.addAttribute(getLinkageAttrName(),
1034                       builder.getI64IntegerAttr(static_cast<int64_t>(linkage)));
1035   if (addrSpace != 0)
1036     result.addAttribute("addr_space", builder.getI32IntegerAttr(addrSpace));
1037   result.attributes.append(attrs.begin(), attrs.end());
1038   result.addRegion();
1039 }
1040 
1041 static void printGlobalOp(OpAsmPrinter &p, GlobalOp op) {
1042   p << op.getOperationName() << ' ' << stringifyLinkage(op.linkage()) << ' ';
1043   if (op.constant())
1044     p << "constant ";
1045   p.printSymbolName(op.sym_name());
1046   p << '(';
1047   if (auto value = op.getValueOrNull())
1048     p.printAttribute(value);
1049   p << ')';
1050   p.printOptionalAttrDict(op.getAttrs(),
1051                           {SymbolTable::getSymbolAttrName(), "type", "constant",
1052                            "value", getLinkageAttrName()});
1053 
1054   // Print the trailing type unless it's a string global.
1055   if (op.getValueOrNull().dyn_cast_or_null<StringAttr>())
1056     return;
1057   p << " : " << op.type();
1058 
1059   Region &initializer = op.getInitializerRegion();
1060   if (!initializer.empty())
1061     p.printRegion(initializer, /*printEntryBlockArgs=*/false);
1062 }
1063 
1064 //===----------------------------------------------------------------------===//
1065 // Verifier for LLVM::DialectCastOp.
1066 //===----------------------------------------------------------------------===//
1067 
1068 static LogicalResult verify(DialectCastOp op) {
1069   auto verifyMLIRCastType = [&op](Type type) -> LogicalResult {
1070     if (auto llvmType = type.dyn_cast<LLVM::LLVMType>()) {
1071       if (llvmType.isVectorTy())
1072         llvmType = llvmType.getVectorElementType();
1073       if (llvmType.isIntegerTy() || llvmType.isBFloatTy() ||
1074           llvmType.isHalfTy() || llvmType.isFloatTy() ||
1075           llvmType.isDoubleTy()) {
1076         return success();
1077       }
1078       return op.emitOpError("type must be non-index integer types, float "
1079                             "types, or vector of mentioned types.");
1080     }
1081     if (auto vectorType = type.dyn_cast<VectorType>()) {
1082       if (vectorType.getShape().size() > 1)
1083         return op.emitOpError("only 1-d vector is allowed");
1084       type = vectorType.getElementType();
1085     }
1086     if (type.isSignlessIntOrFloat())
1087       return success();
1088     // Note that memrefs are not supported. We currently don't have a use case
1089     // for it, but even if we do, there are challenges:
1090     // * if we allow memrefs to cast from/to memref descriptors, then the
1091     // semantics of the cast op depends on the implementation detail of the
1092     // descriptor.
1093     // * if we allow memrefs to cast from/to bare pointers, some users might
1094     // alternatively want metadata that only present in the descriptor.
1095     //
1096     // TODO: re-evaluate the memref cast design when it's needed.
1097     return op.emitOpError("type must be non-index integer types, float types, "
1098                           "or vector of mentioned types.");
1099   };
1100   return failure(failed(verifyMLIRCastType(op.in().getType())) ||
1101                  failed(verifyMLIRCastType(op.getType())));
1102 }
1103 
1104 // Parses one of the keywords provided in the list `keywords` and returns the
1105 // position of the parsed keyword in the list. If none of the keywords from the
1106 // list is parsed, returns -1.
1107 static int parseOptionalKeywordAlternative(OpAsmParser &parser,
1108                                            ArrayRef<StringRef> keywords) {
1109   for (auto en : llvm::enumerate(keywords)) {
1110     if (succeeded(parser.parseOptionalKeyword(en.value())))
1111       return en.index();
1112   }
1113   return -1;
1114 }
1115 
1116 namespace {
1117 template <typename Ty> struct EnumTraits {};
1118 
1119 #define REGISTER_ENUM_TYPE(Ty)                                                 \
1120   template <> struct EnumTraits<Ty> {                                          \
1121     static StringRef stringify(Ty value) { return stringify##Ty(value); }      \
1122     static unsigned getMaxEnumVal() { return getMaxEnumValFor##Ty(); }         \
1123   }
1124 
1125 REGISTER_ENUM_TYPE(Linkage);
1126 } // end namespace
1127 
1128 template <typename EnumTy>
1129 static ParseResult parseOptionalLLVMKeyword(OpAsmParser &parser,
1130                                             OperationState &result,
1131                                             StringRef name) {
1132   SmallVector<StringRef, 10> names;
1133   for (unsigned i = 0, e = getMaxEnumValForLinkage(); i <= e; ++i)
1134     names.push_back(EnumTraits<EnumTy>::stringify(static_cast<EnumTy>(i)));
1135 
1136   int index = parseOptionalKeywordAlternative(parser, names);
1137   if (index == -1)
1138     return failure();
1139   result.addAttribute(name, parser.getBuilder().getI64IntegerAttr(index));
1140   return success();
1141 }
1142 
1143 // operation ::= `llvm.mlir.global` linkage? `constant`? `@` identifier
1144 //               `(` attribute? `)` attribute-list? (`:` type)? region?
1145 //
1146 // The type can be omitted for string attributes, in which case it will be
1147 // inferred from the value of the string as [strlen(value) x i8].
1148 static ParseResult parseGlobalOp(OpAsmParser &parser, OperationState &result) {
1149   if (failed(parseOptionalLLVMKeyword<Linkage>(parser, result,
1150                                                getLinkageAttrName())))
1151     result.addAttribute(getLinkageAttrName(),
1152                         parser.getBuilder().getI64IntegerAttr(
1153                             static_cast<int64_t>(LLVM::Linkage::External)));
1154 
1155   if (succeeded(parser.parseOptionalKeyword("constant")))
1156     result.addAttribute("constant", parser.getBuilder().getUnitAttr());
1157 
1158   StringAttr name;
1159   if (parser.parseSymbolName(name, SymbolTable::getSymbolAttrName(),
1160                              result.attributes) ||
1161       parser.parseLParen())
1162     return failure();
1163 
1164   Attribute value;
1165   if (parser.parseOptionalRParen()) {
1166     if (parser.parseAttribute(value, "value", result.attributes) ||
1167         parser.parseRParen())
1168       return failure();
1169   }
1170 
1171   SmallVector<Type, 1> types;
1172   if (parser.parseOptionalAttrDict(result.attributes) ||
1173       parser.parseOptionalColonTypeList(types))
1174     return failure();
1175 
1176   if (types.size() > 1)
1177     return parser.emitError(parser.getNameLoc(), "expected zero or one type");
1178 
1179   Region &initRegion = *result.addRegion();
1180   if (types.empty()) {
1181     if (auto strAttr = value.dyn_cast_or_null<StringAttr>()) {
1182       MLIRContext *context = parser.getBuilder().getContext();
1183       auto arrayType = LLVM::LLVMType::getArrayTy(
1184           LLVM::LLVMType::getInt8Ty(context), strAttr.getValue().size());
1185       types.push_back(arrayType);
1186     } else {
1187       return parser.emitError(parser.getNameLoc(),
1188                               "type can only be omitted for string globals");
1189     }
1190   } else if (parser.parseOptionalRegion(initRegion, /*arguments=*/{},
1191                                         /*argTypes=*/{})) {
1192     return failure();
1193   }
1194 
1195   result.addAttribute("type", TypeAttr::get(types[0]));
1196   return success();
1197 }
1198 
1199 static LogicalResult verify(GlobalOp op) {
1200   if (!LLVMPointerType::isValidElementType(op.getType()))
1201     return op.emitOpError(
1202         "expects type to be a valid element type for an LLVM pointer");
1203   if (op.getParentOp() && !satisfiesLLVMModule(op.getParentOp()))
1204     return op.emitOpError("must appear at the module level");
1205 
1206   if (auto strAttr = op.getValueOrNull().dyn_cast_or_null<StringAttr>()) {
1207     auto type = op.getType();
1208     if (!type.isArrayTy() || !type.getArrayElementType().isIntegerTy(8) ||
1209         type.getArrayNumElements() != strAttr.getValue().size())
1210       return op.emitOpError(
1211           "requires an i8 array type of the length equal to that of the string "
1212           "attribute");
1213   }
1214 
1215   if (Block *b = op.getInitializerBlock()) {
1216     ReturnOp ret = cast<ReturnOp>(b->getTerminator());
1217     if (ret.operand_type_begin() == ret.operand_type_end())
1218       return op.emitOpError("initializer region cannot return void");
1219     if (*ret.operand_type_begin() != op.getType())
1220       return op.emitOpError("initializer region type ")
1221              << *ret.operand_type_begin() << " does not match global type "
1222              << op.getType();
1223 
1224     if (op.getValueOrNull())
1225       return op.emitOpError("cannot have both initializer value and region");
1226   }
1227   return success();
1228 }
1229 
1230 //===----------------------------------------------------------------------===//
1231 // Printing/parsing for LLVM::ShuffleVectorOp.
1232 //===----------------------------------------------------------------------===//
1233 // Expects vector to be of wrapped LLVM vector type and position to be of
1234 // wrapped LLVM i32 type.
1235 void LLVM::ShuffleVectorOp::build(OpBuilder &b, OperationState &result,
1236                                   Value v1, Value v2, ArrayAttr mask,
1237                                   ArrayRef<NamedAttribute> attrs) {
1238   auto wrappedContainerType1 = v1.getType().cast<LLVM::LLVMType>();
1239   auto vType = LLVMType::getVectorTy(
1240       wrappedContainerType1.getVectorElementType(), mask.size());
1241   build(b, result, vType, v1, v2, mask);
1242   result.addAttributes(attrs);
1243 }
1244 
1245 static void printShuffleVectorOp(OpAsmPrinter &p, ShuffleVectorOp &op) {
1246   p << op.getOperationName() << ' ' << op.v1() << ", " << op.v2() << " "
1247     << op.mask();
1248   p.printOptionalAttrDict(op.getAttrs(), {"mask"});
1249   p << " : " << op.v1().getType() << ", " << op.v2().getType();
1250 }
1251 
1252 // <operation> ::= `llvm.shufflevector` ssa-use `, ` ssa-use
1253 //                 `[` integer-literal (`,` integer-literal)* `]`
1254 //                 attribute-dict? `:` type
1255 static ParseResult parseShuffleVectorOp(OpAsmParser &parser,
1256                                         OperationState &result) {
1257   llvm::SMLoc loc;
1258   OpAsmParser::OperandType v1, v2;
1259   ArrayAttr maskAttr;
1260   Type typeV1, typeV2;
1261   if (parser.getCurrentLocation(&loc) || parser.parseOperand(v1) ||
1262       parser.parseComma() || parser.parseOperand(v2) ||
1263       parser.parseAttribute(maskAttr, "mask", result.attributes) ||
1264       parser.parseOptionalAttrDict(result.attributes) ||
1265       parser.parseColonType(typeV1) || parser.parseComma() ||
1266       parser.parseType(typeV2) ||
1267       parser.resolveOperand(v1, typeV1, result.operands) ||
1268       parser.resolveOperand(v2, typeV2, result.operands))
1269     return failure();
1270   auto wrappedContainerType1 = typeV1.dyn_cast<LLVM::LLVMType>();
1271   if (!wrappedContainerType1 || !wrappedContainerType1.isVectorTy())
1272     return parser.emitError(
1273         loc, "expected LLVM IR dialect vector type for operand #1");
1274   auto vType = LLVMType::getVectorTy(
1275       wrappedContainerType1.getVectorElementType(), maskAttr.size());
1276   result.addTypes(vType);
1277   return success();
1278 }
1279 
1280 //===----------------------------------------------------------------------===//
1281 // Implementations for LLVM::LLVMFuncOp.
1282 //===----------------------------------------------------------------------===//
1283 
1284 // Add the entry block to the function.
1285 Block *LLVMFuncOp::addEntryBlock() {
1286   assert(empty() && "function already has an entry block");
1287   assert(!isVarArg() && "unimplemented: non-external variadic functions");
1288 
1289   auto *entry = new Block;
1290   push_back(entry);
1291 
1292   LLVMType type = getType();
1293   for (unsigned i = 0, e = type.getFunctionNumParams(); i < e; ++i)
1294     entry->addArgument(type.getFunctionParamType(i));
1295   return entry;
1296 }
1297 
1298 void LLVMFuncOp::build(OpBuilder &builder, OperationState &result,
1299                        StringRef name, LLVMType type, LLVM::Linkage linkage,
1300                        ArrayRef<NamedAttribute> attrs,
1301                        ArrayRef<MutableDictionaryAttr> argAttrs) {
1302   result.addRegion();
1303   result.addAttribute(SymbolTable::getSymbolAttrName(),
1304                       builder.getStringAttr(name));
1305   result.addAttribute("type", TypeAttr::get(type));
1306   result.addAttribute(getLinkageAttrName(),
1307                       builder.getI64IntegerAttr(static_cast<int64_t>(linkage)));
1308   result.attributes.append(attrs.begin(), attrs.end());
1309   if (argAttrs.empty())
1310     return;
1311 
1312   unsigned numInputs = type.getFunctionNumParams();
1313   assert(numInputs == argAttrs.size() &&
1314          "expected as many argument attribute lists as arguments");
1315   SmallString<8> argAttrName;
1316   for (unsigned i = 0; i < numInputs; ++i)
1317     if (auto argDict = argAttrs[i].getDictionary(builder.getContext()))
1318       result.addAttribute(getArgAttrName(i, argAttrName), argDict);
1319 }
1320 
1321 // Builds an LLVM function type from the given lists of input and output types.
1322 // Returns a null type if any of the types provided are non-LLVM types, or if
1323 // there is more than one output type.
1324 static Type buildLLVMFunctionType(OpAsmParser &parser, llvm::SMLoc loc,
1325                                   ArrayRef<Type> inputs, ArrayRef<Type> outputs,
1326                                   impl::VariadicFlag variadicFlag) {
1327   Builder &b = parser.getBuilder();
1328   if (outputs.size() > 1) {
1329     parser.emitError(loc, "failed to construct function type: expected zero or "
1330                           "one function result");
1331     return {};
1332   }
1333 
1334   // Convert inputs to LLVM types, exit early on error.
1335   SmallVector<LLVMType, 4> llvmInputs;
1336   for (auto t : inputs) {
1337     auto llvmTy = t.dyn_cast<LLVMType>();
1338     if (!llvmTy) {
1339       parser.emitError(loc, "failed to construct function type: expected LLVM "
1340                             "type for function arguments");
1341       return {};
1342     }
1343     llvmInputs.push_back(llvmTy);
1344   }
1345 
1346   // No output is denoted as "void" in LLVM type system.
1347   LLVMType llvmOutput = outputs.empty() ? LLVMType::getVoidTy(b.getContext())
1348                                         : outputs.front().dyn_cast<LLVMType>();
1349   if (!llvmOutput) {
1350     parser.emitError(loc, "failed to construct function type: expected LLVM "
1351                           "type for function results");
1352     return {};
1353   }
1354   return LLVMType::getFunctionTy(llvmOutput, llvmInputs,
1355                                  variadicFlag.isVariadic());
1356 }
1357 
1358 // Parses an LLVM function.
1359 //
1360 // operation ::= `llvm.func` linkage? function-signature function-attributes?
1361 //               function-body
1362 //
1363 static ParseResult parseLLVMFuncOp(OpAsmParser &parser,
1364                                    OperationState &result) {
1365   // Default to external linkage if no keyword is provided.
1366   if (failed(parseOptionalLLVMKeyword<Linkage>(parser, result,
1367                                                getLinkageAttrName())))
1368     result.addAttribute(getLinkageAttrName(),
1369                         parser.getBuilder().getI64IntegerAttr(
1370                             static_cast<int64_t>(LLVM::Linkage::External)));
1371 
1372   StringAttr nameAttr;
1373   SmallVector<OpAsmParser::OperandType, 8> entryArgs;
1374   SmallVector<NamedAttrList, 1> argAttrs;
1375   SmallVector<NamedAttrList, 1> resultAttrs;
1376   SmallVector<Type, 8> argTypes;
1377   SmallVector<Type, 4> resultTypes;
1378   bool isVariadic;
1379 
1380   auto signatureLocation = parser.getCurrentLocation();
1381   if (parser.parseSymbolName(nameAttr, SymbolTable::getSymbolAttrName(),
1382                              result.attributes) ||
1383       impl::parseFunctionSignature(parser, /*allowVariadic=*/true, entryArgs,
1384                                    argTypes, argAttrs, isVariadic, resultTypes,
1385                                    resultAttrs))
1386     return failure();
1387 
1388   auto type =
1389       buildLLVMFunctionType(parser, signatureLocation, argTypes, resultTypes,
1390                             impl::VariadicFlag(isVariadic));
1391   if (!type)
1392     return failure();
1393   result.addAttribute(impl::getTypeAttrName(), TypeAttr::get(type));
1394 
1395   if (failed(parser.parseOptionalAttrDictWithKeyword(result.attributes)))
1396     return failure();
1397   impl::addArgAndResultAttrs(parser.getBuilder(), result, argAttrs,
1398                              resultAttrs);
1399 
1400   auto *body = result.addRegion();
1401   return parser.parseOptionalRegion(
1402       *body, entryArgs, entryArgs.empty() ? ArrayRef<Type>() : argTypes);
1403 }
1404 
1405 // Print the LLVMFuncOp. Collects argument and result types and passes them to
1406 // helper functions. Drops "void" result since it cannot be parsed back. Skips
1407 // the external linkage since it is the default value.
1408 static void printLLVMFuncOp(OpAsmPrinter &p, LLVMFuncOp op) {
1409   p << op.getOperationName() << ' ';
1410   if (op.linkage() != LLVM::Linkage::External)
1411     p << stringifyLinkage(op.linkage()) << ' ';
1412   p.printSymbolName(op.getName());
1413 
1414   LLVMType fnType = op.getType();
1415   SmallVector<Type, 8> argTypes;
1416   SmallVector<Type, 1> resTypes;
1417   argTypes.reserve(fnType.getFunctionNumParams());
1418   for (unsigned i = 0, e = fnType.getFunctionNumParams(); i < e; ++i)
1419     argTypes.push_back(fnType.getFunctionParamType(i));
1420 
1421   LLVMType returnType = fnType.getFunctionResultType();
1422   if (!returnType.isVoidTy())
1423     resTypes.push_back(returnType);
1424 
1425   impl::printFunctionSignature(p, op, argTypes, op.isVarArg(), resTypes);
1426   impl::printFunctionAttributes(p, op, argTypes.size(), resTypes.size(),
1427                                 {getLinkageAttrName()});
1428 
1429   // Print the body if this is not an external function.
1430   Region &body = op.body();
1431   if (!body.empty())
1432     p.printRegion(body, /*printEntryBlockArgs=*/false,
1433                   /*printBlockTerminators=*/true);
1434 }
1435 
1436 // Hook for OpTrait::FunctionLike, called after verifying that the 'type'
1437 // attribute is present.  This can check for preconditions of the
1438 // getNumArguments hook not failing.
1439 LogicalResult LLVMFuncOp::verifyType() {
1440   auto llvmType = getTypeAttr().getValue().dyn_cast_or_null<LLVMType>();
1441   if (!llvmType || !llvmType.isFunctionTy())
1442     return emitOpError("requires '" + getTypeAttrName() +
1443                        "' attribute of wrapped LLVM function type");
1444 
1445   return success();
1446 }
1447 
1448 // Hook for OpTrait::FunctionLike, returns the number of function arguments.
1449 // Depends on the type attribute being correct as checked by verifyType
1450 unsigned LLVMFuncOp::getNumFuncArguments() {
1451   return getType().getFunctionNumParams();
1452 }
1453 
1454 // Hook for OpTrait::FunctionLike, returns the number of function results.
1455 // Depends on the type attribute being correct as checked by verifyType
1456 unsigned LLVMFuncOp::getNumFuncResults() {
1457   // We model LLVM functions that return void as having zero results,
1458   // and all others as having one result.
1459   // If we modeled a void return as one result, then it would be possible to
1460   // attach an MLIR result attribute to it, and it isn't clear what semantics we
1461   // would assign to that.
1462   if (getType().getFunctionResultType().isVoidTy())
1463     return 0;
1464   return 1;
1465 }
1466 
1467 // Verifies LLVM- and implementation-specific properties of the LLVM func Op:
1468 // - functions don't have 'common' linkage
1469 // - external functions have 'external' or 'extern_weak' linkage;
1470 // - vararg is (currently) only supported for external functions;
1471 // - entry block arguments are of LLVM types and match the function signature.
1472 static LogicalResult verify(LLVMFuncOp op) {
1473   if (op.linkage() == LLVM::Linkage::Common)
1474     return op.emitOpError()
1475            << "functions cannot have '"
1476            << stringifyLinkage(LLVM::Linkage::Common) << "' linkage";
1477 
1478   if (op.isExternal()) {
1479     if (op.linkage() != LLVM::Linkage::External &&
1480         op.linkage() != LLVM::Linkage::ExternWeak)
1481       return op.emitOpError()
1482              << "external functions must have '"
1483              << stringifyLinkage(LLVM::Linkage::External) << "' or '"
1484              << stringifyLinkage(LLVM::Linkage::ExternWeak) << "' linkage";
1485     return success();
1486   }
1487 
1488   if (op.isVarArg())
1489     return op.emitOpError("only external functions can be variadic");
1490 
1491   unsigned numArguments = op.getType().getFunctionNumParams();
1492   Block &entryBlock = op.front();
1493   for (unsigned i = 0; i < numArguments; ++i) {
1494     Type argType = entryBlock.getArgument(i).getType();
1495     auto argLLVMType = argType.dyn_cast<LLVMType>();
1496     if (!argLLVMType)
1497       return op.emitOpError("entry block argument #")
1498              << i << " is not of LLVM type";
1499     if (op.getType().getFunctionParamType(i) != argLLVMType)
1500       return op.emitOpError("the type of entry block argument #")
1501              << i << " does not match the function signature";
1502   }
1503 
1504   return success();
1505 }
1506 
1507 //===----------------------------------------------------------------------===//
1508 // Verification for LLVM::NullOp.
1509 //===----------------------------------------------------------------------===//
1510 
1511 // Only LLVM pointer types are supported.
1512 static LogicalResult verify(LLVM::NullOp op) {
1513   auto llvmType = op.getType().dyn_cast<LLVM::LLVMType>();
1514   if (!llvmType || !llvmType.isPointerTy())
1515     return op.emitOpError("expected LLVM IR pointer type");
1516   return success();
1517 }
1518 
1519 //===----------------------------------------------------------------------===//
1520 // Verification for LLVM::ConstantOp.
1521 //===----------------------------------------------------------------------===//
1522 
1523 static LogicalResult verify(LLVM::ConstantOp op) {
1524   if (!(op.value().isa<IntegerAttr>() || op.value().isa<FloatAttr>() ||
1525         op.value().isa<ElementsAttr>() || op.value().isa<StringAttr>()))
1526     return op.emitOpError()
1527            << "only supports integer, float, string or elements attributes";
1528   return success();
1529 }
1530 
1531 //===----------------------------------------------------------------------===//
1532 // Utility functions for parsing atomic ops
1533 //===----------------------------------------------------------------------===//
1534 
1535 // Helper function to parse a keyword into the specified attribute named by
1536 // `attrName`. The keyword must match one of the string values defined by the
1537 // AtomicBinOp enum. The resulting I64 attribute is added to the `result`
1538 // state.
1539 static ParseResult parseAtomicBinOp(OpAsmParser &parser, OperationState &result,
1540                                     StringRef attrName) {
1541   llvm::SMLoc loc;
1542   StringRef keyword;
1543   if (parser.getCurrentLocation(&loc) || parser.parseKeyword(&keyword))
1544     return failure();
1545 
1546   // Replace the keyword `keyword` with an integer attribute.
1547   auto kind = symbolizeAtomicBinOp(keyword);
1548   if (!kind) {
1549     return parser.emitError(loc)
1550            << "'" << keyword << "' is an incorrect value of the '" << attrName
1551            << "' attribute";
1552   }
1553 
1554   auto value = static_cast<int64_t>(kind.getValue());
1555   auto attr = parser.getBuilder().getI64IntegerAttr(value);
1556   result.addAttribute(attrName, attr);
1557 
1558   return success();
1559 }
1560 
1561 // Helper function to parse a keyword into the specified attribute named by
1562 // `attrName`. The keyword must match one of the string values defined by the
1563 // AtomicOrdering enum. The resulting I64 attribute is added to the `result`
1564 // state.
1565 static ParseResult parseAtomicOrdering(OpAsmParser &parser,
1566                                        OperationState &result,
1567                                        StringRef attrName) {
1568   llvm::SMLoc loc;
1569   StringRef ordering;
1570   if (parser.getCurrentLocation(&loc) || parser.parseKeyword(&ordering))
1571     return failure();
1572 
1573   // Replace the keyword `ordering` with an integer attribute.
1574   auto kind = symbolizeAtomicOrdering(ordering);
1575   if (!kind) {
1576     return parser.emitError(loc)
1577            << "'" << ordering << "' is an incorrect value of the '" << attrName
1578            << "' attribute";
1579   }
1580 
1581   auto value = static_cast<int64_t>(kind.getValue());
1582   auto attr = parser.getBuilder().getI64IntegerAttr(value);
1583   result.addAttribute(attrName, attr);
1584 
1585   return success();
1586 }
1587 
1588 //===----------------------------------------------------------------------===//
1589 // Printer, parser and verifier for LLVM::AtomicRMWOp.
1590 //===----------------------------------------------------------------------===//
1591 
1592 static void printAtomicRMWOp(OpAsmPrinter &p, AtomicRMWOp &op) {
1593   p << op.getOperationName() << ' ' << stringifyAtomicBinOp(op.bin_op()) << ' '
1594     << op.ptr() << ", " << op.val() << ' '
1595     << stringifyAtomicOrdering(op.ordering()) << ' ';
1596   p.printOptionalAttrDict(op.getAttrs(), {"bin_op", "ordering"});
1597   p << " : " << op.res().getType();
1598 }
1599 
1600 // <operation> ::= `llvm.atomicrmw` keyword ssa-use `,` ssa-use keyword
1601 //                 attribute-dict? `:` type
1602 static ParseResult parseAtomicRMWOp(OpAsmParser &parser,
1603                                     OperationState &result) {
1604   LLVMType type;
1605   OpAsmParser::OperandType ptr, val;
1606   if (parseAtomicBinOp(parser, result, "bin_op") || parser.parseOperand(ptr) ||
1607       parser.parseComma() || parser.parseOperand(val) ||
1608       parseAtomicOrdering(parser, result, "ordering") ||
1609       parser.parseOptionalAttrDict(result.attributes) ||
1610       parser.parseColonType(type) ||
1611       parser.resolveOperand(ptr, type.getPointerTo(), result.operands) ||
1612       parser.resolveOperand(val, type, result.operands))
1613     return failure();
1614 
1615   result.addTypes(type);
1616   return success();
1617 }
1618 
1619 static LogicalResult verify(AtomicRMWOp op) {
1620   auto ptrType = op.ptr().getType().cast<LLVM::LLVMType>();
1621   auto valType = op.val().getType().cast<LLVM::LLVMType>();
1622   if (valType != ptrType.getPointerElementTy())
1623     return op.emitOpError("expected LLVM IR element type for operand #0 to "
1624                           "match type for operand #1");
1625   auto resType = op.res().getType().cast<LLVM::LLVMType>();
1626   if (resType != valType)
1627     return op.emitOpError(
1628         "expected LLVM IR result type to match type for operand #1");
1629   if (op.bin_op() == AtomicBinOp::fadd || op.bin_op() == AtomicBinOp::fsub) {
1630     if (!valType.isFloatingPointTy())
1631       return op.emitOpError("expected LLVM IR floating point type");
1632   } else if (op.bin_op() == AtomicBinOp::xchg) {
1633     if (!valType.isIntegerTy(8) && !valType.isIntegerTy(16) &&
1634         !valType.isIntegerTy(32) && !valType.isIntegerTy(64) &&
1635         !valType.isBFloatTy() && !valType.isHalfTy() && !valType.isFloatTy() &&
1636         !valType.isDoubleTy())
1637       return op.emitOpError("unexpected LLVM IR type for 'xchg' bin_op");
1638   } else {
1639     if (!valType.isIntegerTy(8) && !valType.isIntegerTy(16) &&
1640         !valType.isIntegerTy(32) && !valType.isIntegerTy(64))
1641       return op.emitOpError("expected LLVM IR integer type");
1642   }
1643   return success();
1644 }
1645 
1646 //===----------------------------------------------------------------------===//
1647 // Printer, parser and verifier for LLVM::AtomicCmpXchgOp.
1648 //===----------------------------------------------------------------------===//
1649 
1650 static void printAtomicCmpXchgOp(OpAsmPrinter &p, AtomicCmpXchgOp &op) {
1651   p << op.getOperationName() << ' ' << op.ptr() << ", " << op.cmp() << ", "
1652     << op.val() << ' ' << stringifyAtomicOrdering(op.success_ordering()) << ' '
1653     << stringifyAtomicOrdering(op.failure_ordering());
1654   p.printOptionalAttrDict(op.getAttrs(),
1655                           {"success_ordering", "failure_ordering"});
1656   p << " : " << op.val().getType();
1657 }
1658 
1659 // <operation> ::= `llvm.cmpxchg` ssa-use `,` ssa-use `,` ssa-use
1660 //                 keyword keyword attribute-dict? `:` type
1661 static ParseResult parseAtomicCmpXchgOp(OpAsmParser &parser,
1662                                         OperationState &result) {
1663   auto &builder = parser.getBuilder();
1664   LLVMType type;
1665   OpAsmParser::OperandType ptr, cmp, val;
1666   if (parser.parseOperand(ptr) || parser.parseComma() ||
1667       parser.parseOperand(cmp) || parser.parseComma() ||
1668       parser.parseOperand(val) ||
1669       parseAtomicOrdering(parser, result, "success_ordering") ||
1670       parseAtomicOrdering(parser, result, "failure_ordering") ||
1671       parser.parseOptionalAttrDict(result.attributes) ||
1672       parser.parseColonType(type) ||
1673       parser.resolveOperand(ptr, type.getPointerTo(), result.operands) ||
1674       parser.resolveOperand(cmp, type, result.operands) ||
1675       parser.resolveOperand(val, type, result.operands))
1676     return failure();
1677 
1678   auto boolType = LLVMType::getInt1Ty(builder.getContext());
1679   auto resultType = LLVMType::getStructTy(type, boolType);
1680   result.addTypes(resultType);
1681 
1682   return success();
1683 }
1684 
1685 static LogicalResult verify(AtomicCmpXchgOp op) {
1686   auto ptrType = op.ptr().getType().cast<LLVM::LLVMType>();
1687   if (!ptrType.isPointerTy())
1688     return op.emitOpError("expected LLVM IR pointer type for operand #0");
1689   auto cmpType = op.cmp().getType().cast<LLVM::LLVMType>();
1690   auto valType = op.val().getType().cast<LLVM::LLVMType>();
1691   if (cmpType != ptrType.getPointerElementTy() || cmpType != valType)
1692     return op.emitOpError("expected LLVM IR element type for operand #0 to "
1693                           "match type for all other operands");
1694   if (!valType.isPointerTy() && !valType.isIntegerTy(8) &&
1695       !valType.isIntegerTy(16) && !valType.isIntegerTy(32) &&
1696       !valType.isIntegerTy(64) && !valType.isBFloatTy() &&
1697       !valType.isHalfTy() && !valType.isFloatTy() && !valType.isDoubleTy())
1698     return op.emitOpError("unexpected LLVM IR type");
1699   if (op.success_ordering() < AtomicOrdering::monotonic ||
1700       op.failure_ordering() < AtomicOrdering::monotonic)
1701     return op.emitOpError("ordering must be at least 'monotonic'");
1702   if (op.failure_ordering() == AtomicOrdering::release ||
1703       op.failure_ordering() == AtomicOrdering::acq_rel)
1704     return op.emitOpError("failure ordering cannot be 'release' or 'acq_rel'");
1705   return success();
1706 }
1707 
1708 //===----------------------------------------------------------------------===//
1709 // Printer, parser and verifier for LLVM::FenceOp.
1710 //===----------------------------------------------------------------------===//
1711 
1712 // <operation> ::= `llvm.fence` (`syncscope(`strAttr`)`)? keyword
1713 // attribute-dict?
1714 static ParseResult parseFenceOp(OpAsmParser &parser, OperationState &result) {
1715   StringAttr sScope;
1716   StringRef syncscopeKeyword = "syncscope";
1717   if (!failed(parser.parseOptionalKeyword(syncscopeKeyword))) {
1718     if (parser.parseLParen() ||
1719         parser.parseAttribute(sScope, syncscopeKeyword, result.attributes) ||
1720         parser.parseRParen())
1721       return failure();
1722   } else {
1723     result.addAttribute(syncscopeKeyword,
1724                         parser.getBuilder().getStringAttr(""));
1725   }
1726   if (parseAtomicOrdering(parser, result, "ordering") ||
1727       parser.parseOptionalAttrDict(result.attributes))
1728     return failure();
1729   return success();
1730 }
1731 
1732 static void printFenceOp(OpAsmPrinter &p, FenceOp &op) {
1733   StringRef syncscopeKeyword = "syncscope";
1734   p << op.getOperationName() << ' ';
1735   if (!op.getAttr(syncscopeKeyword).cast<StringAttr>().getValue().empty())
1736     p << "syncscope(" << op.getAttr(syncscopeKeyword) << ") ";
1737   p << stringifyAtomicOrdering(op.ordering());
1738 }
1739 
1740 static LogicalResult verify(FenceOp &op) {
1741   if (op.ordering() == AtomicOrdering::not_atomic ||
1742       op.ordering() == AtomicOrdering::unordered ||
1743       op.ordering() == AtomicOrdering::monotonic)
1744     return op.emitOpError("can be given only acquire, release, acq_rel, "
1745                           "and seq_cst orderings");
1746   return success();
1747 }
1748 
1749 //===----------------------------------------------------------------------===//
1750 // LLVMDialect initialization, type parsing, and registration.
1751 //===----------------------------------------------------------------------===//
1752 
1753 void LLVMDialect::initialize() {
1754   // clang-format off
1755   addTypes<LLVMVoidType,
1756            LLVMHalfType,
1757            LLVMBFloatType,
1758            LLVMFloatType,
1759            LLVMDoubleType,
1760            LLVMFP128Type,
1761            LLVMX86FP80Type,
1762            LLVMPPCFP128Type,
1763            LLVMX86MMXType,
1764            LLVMTokenType,
1765            LLVMLabelType,
1766            LLVMMetadataType,
1767            LLVMFunctionType,
1768            LLVMIntegerType,
1769            LLVMPointerType,
1770            LLVMFixedVectorType,
1771            LLVMScalableVectorType,
1772            LLVMArrayType,
1773            LLVMStructType>();
1774   // clang-format on
1775   addOperations<
1776 #define GET_OP_LIST
1777 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
1778       >();
1779 
1780   // Support unknown operations because not all LLVM operations are registered.
1781   allowUnknownOperations();
1782 }
1783 
1784 #define GET_OP_CLASSES
1785 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
1786 
1787 /// Parse a type registered to this dialect.
1788 Type LLVMDialect::parseType(DialectAsmParser &parser) const {
1789   return detail::parseType(parser);
1790 }
1791 
1792 /// Print a type registered to this dialect.
1793 void LLVMDialect::printType(Type type, DialectAsmPrinter &os) const {
1794   return detail::printType(type.cast<LLVMType>(), os);
1795 }
1796 
1797 LogicalResult LLVMDialect::verifyDataLayoutString(
1798     StringRef descr, llvm::function_ref<void(const Twine &)> reportError) {
1799   llvm::Expected<llvm::DataLayout> maybeDataLayout =
1800       llvm::DataLayout::parse(descr);
1801   if (maybeDataLayout)
1802     return success();
1803 
1804   std::string message;
1805   llvm::raw_string_ostream messageStream(message);
1806   llvm::logAllUnhandledErrors(maybeDataLayout.takeError(), messageStream);
1807   reportError("invalid data layout descriptor: " + messageStream.str());
1808   return failure();
1809 }
1810 
1811 /// Verify LLVM dialect attributes.
1812 LogicalResult LLVMDialect::verifyOperationAttribute(Operation *op,
1813                                                     NamedAttribute attr) {
1814   // If the data layout attribute is present, it must use the LLVM data layout
1815   // syntax. Try parsing it and report errors in case of failure. Users of this
1816   // attribute may assume it is well-formed and can pass it to the (asserting)
1817   // llvm::DataLayout constructor.
1818   if (attr.first.strref() != LLVM::LLVMDialect::getDataLayoutAttrName())
1819     return success();
1820   if (auto stringAttr = attr.second.dyn_cast<StringAttr>())
1821     return verifyDataLayoutString(
1822         stringAttr.getValue(),
1823         [op](const Twine &message) { op->emitOpError() << message.str(); });
1824 
1825   return op->emitOpError() << "expected '"
1826                            << LLVM::LLVMDialect::getDataLayoutAttrName()
1827                            << "' to be a string attribute";
1828 }
1829 
1830 /// Verify LLVMIR function argument attributes.
1831 LogicalResult LLVMDialect::verifyRegionArgAttribute(Operation *op,
1832                                                     unsigned regionIdx,
1833                                                     unsigned argIdx,
1834                                                     NamedAttribute argAttr) {
1835   // Check that llvm.noalias is a boolean attribute.
1836   if (argAttr.first == "llvm.noalias" && !argAttr.second.isa<BoolAttr>())
1837     return op->emitError()
1838            << "llvm.noalias argument attribute of non boolean type";
1839   // Check that llvm.align is an integer attribute.
1840   if (argAttr.first == "llvm.align" && !argAttr.second.isa<IntegerAttr>())
1841     return op->emitError()
1842            << "llvm.align argument attribute of non integer type";
1843   return success();
1844 }
1845 
1846 //===----------------------------------------------------------------------===//
1847 // Utility functions.
1848 //===----------------------------------------------------------------------===//
1849 
1850 Value mlir::LLVM::createGlobalString(Location loc, OpBuilder &builder,
1851                                      StringRef name, StringRef value,
1852                                      LLVM::Linkage linkage) {
1853   assert(builder.getInsertionBlock() &&
1854          builder.getInsertionBlock()->getParentOp() &&
1855          "expected builder to point to a block constrained in an op");
1856   auto module =
1857       builder.getInsertionBlock()->getParentOp()->getParentOfType<ModuleOp>();
1858   assert(module && "builder points to an op outside of a module");
1859 
1860   // Create the global at the entry of the module.
1861   OpBuilder moduleBuilder(module.getBodyRegion());
1862   MLIRContext *ctx = builder.getContext();
1863   auto type =
1864       LLVM::LLVMType::getArrayTy(LLVM::LLVMType::getInt8Ty(ctx), value.size());
1865   auto global = moduleBuilder.create<LLVM::GlobalOp>(
1866       loc, type, /*isConstant=*/true, linkage, name,
1867       builder.getStringAttr(value));
1868 
1869   // Get the pointer to the first character in the global string.
1870   Value globalPtr = builder.create<LLVM::AddressOfOp>(loc, global);
1871   Value cst0 = builder.create<LLVM::ConstantOp>(
1872       loc, LLVM::LLVMType::getInt64Ty(ctx),
1873       builder.getIntegerAttr(builder.getIndexType(), 0));
1874   return builder.create<LLVM::GEPOp>(loc, LLVM::LLVMType::getInt8PtrTy(ctx),
1875                                      globalPtr, ValueRange{cst0, cst0});
1876 }
1877 
1878 bool mlir::LLVM::satisfiesLLVMModule(Operation *op) {
1879   return op->hasTrait<OpTrait::SymbolTable>() &&
1880          op->hasTrait<OpTrait::IsIsolatedFromAbove>();
1881 }
1882