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