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()->getSExtValue() != 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   // Extract the result type from the trailing function type.
147   auto funcType = type.dyn_cast<FunctionType>();
148   if (!funcType || funcType.getNumInputs() != 1 ||
149       funcType.getNumResults() != 1)
150     return parser.emitError(
151         trailingTypeLoc,
152         "expected trailing function type with one argument and one result");
153 
154   if (parser.resolveOperand(arraySize, funcType.getInput(0), result.operands))
155     return failure();
156 
157   result.addTypes({funcType.getResult(0)});
158   return success();
159 }
160 
161 //===----------------------------------------------------------------------===//
162 // LLVM::BrOp
163 //===----------------------------------------------------------------------===//
164 
165 Optional<MutableOperandRange>
166 BrOp::getMutableSuccessorOperands(unsigned index) {
167   assert(index == 0 && "invalid successor index");
168   return destOperandsMutable();
169 }
170 
171 //===----------------------------------------------------------------------===//
172 // LLVM::CondBrOp
173 //===----------------------------------------------------------------------===//
174 
175 Optional<MutableOperandRange>
176 CondBrOp::getMutableSuccessorOperands(unsigned index) {
177   assert(index < getNumSuccessors() && "invalid successor index");
178   return index == 0 ? trueDestOperandsMutable() : falseDestOperandsMutable();
179 }
180 
181 //===----------------------------------------------------------------------===//
182 // Builder, printer and parser for for LLVM::LoadOp.
183 //===----------------------------------------------------------------------===//
184 
185 void LoadOp::build(OpBuilder &builder, OperationState &result, Type t,
186                    Value addr, unsigned alignment, bool isVolatile,
187                    bool isNonTemporal) {
188   result.addOperands(addr);
189   result.addTypes(t);
190   if (isVolatile)
191     result.addAttribute(kVolatileAttrName, builder.getUnitAttr());
192   if (isNonTemporal)
193     result.addAttribute(kNonTemporalAttrName, builder.getUnitAttr());
194   if (alignment != 0)
195     result.addAttribute("alignment", builder.getI64IntegerAttr(alignment));
196 }
197 
198 static void printLoadOp(OpAsmPrinter &p, LoadOp &op) {
199   p << op.getOperationName() << ' ';
200   if (op.volatile_())
201     p << "volatile ";
202   p << op.addr();
203   p.printOptionalAttrDict(op.getAttrs(), {kVolatileAttrName});
204   p << " : " << op.addr().getType();
205 }
206 
207 // Extract the pointee type from the LLVM pointer type wrapped in MLIR.  Return
208 // the resulting type wrapped in MLIR, or nullptr on error.
209 static Type getLoadStoreElementType(OpAsmParser &parser, Type type,
210                                     llvm::SMLoc trailingTypeLoc) {
211   auto llvmTy = type.dyn_cast<LLVM::LLVMType>();
212   if (!llvmTy)
213     return parser.emitError(trailingTypeLoc, "expected LLVM IR dialect type"),
214            nullptr;
215   if (!llvmTy.isPointerTy())
216     return parser.emitError(trailingTypeLoc, "expected LLVM pointer type"),
217            nullptr;
218   return llvmTy.getPointerElementTy();
219 }
220 
221 // <operation> ::= `llvm.load` `volatile` ssa-use attribute-dict? `:` type
222 static ParseResult parseLoadOp(OpAsmParser &parser, OperationState &result) {
223   OpAsmParser::OperandType addr;
224   Type type;
225   llvm::SMLoc trailingTypeLoc;
226 
227   if (succeeded(parser.parseOptionalKeyword("volatile")))
228     result.addAttribute(kVolatileAttrName, parser.getBuilder().getUnitAttr());
229 
230   if (parser.parseOperand(addr) ||
231       parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
232       parser.getCurrentLocation(&trailingTypeLoc) || parser.parseType(type) ||
233       parser.resolveOperand(addr, type, result.operands))
234     return failure();
235 
236   Type elemTy = getLoadStoreElementType(parser, type, trailingTypeLoc);
237 
238   result.addTypes(elemTy);
239   return success();
240 }
241 
242 //===----------------------------------------------------------------------===//
243 // Builder, printer and parser for LLVM::StoreOp.
244 //===----------------------------------------------------------------------===//
245 
246 void StoreOp::build(OpBuilder &builder, OperationState &result, Value value,
247                     Value addr, unsigned alignment, bool isVolatile,
248                     bool isNonTemporal) {
249   result.addOperands({value, addr});
250   result.addTypes(ArrayRef<Type>{});
251   if (isVolatile)
252     result.addAttribute(kVolatileAttrName, builder.getUnitAttr());
253   if (isNonTemporal)
254     result.addAttribute(kNonTemporalAttrName, builder.getUnitAttr());
255   if (alignment != 0)
256     result.addAttribute("alignment", builder.getI64IntegerAttr(alignment));
257 }
258 
259 static void printStoreOp(OpAsmPrinter &p, StoreOp &op) {
260   p << op.getOperationName() << ' ';
261   if (op.volatile_())
262     p << "volatile ";
263   p << op.value() << ", " << op.addr();
264   p.printOptionalAttrDict(op.getAttrs(), {kVolatileAttrName});
265   p << " : " << op.addr().getType();
266 }
267 
268 // <operation> ::= `llvm.store` `volatile` ssa-use `,` ssa-use
269 //                 attribute-dict? `:` type
270 static ParseResult parseStoreOp(OpAsmParser &parser, OperationState &result) {
271   OpAsmParser::OperandType addr, value;
272   Type type;
273   llvm::SMLoc trailingTypeLoc;
274 
275   if (succeeded(parser.parseOptionalKeyword("volatile")))
276     result.addAttribute(kVolatileAttrName, parser.getBuilder().getUnitAttr());
277 
278   if (parser.parseOperand(value) || parser.parseComma() ||
279       parser.parseOperand(addr) ||
280       parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
281       parser.getCurrentLocation(&trailingTypeLoc) || parser.parseType(type))
282     return failure();
283 
284   Type elemTy = getLoadStoreElementType(parser, type, trailingTypeLoc);
285   if (!elemTy)
286     return failure();
287 
288   if (parser.resolveOperand(value, elemTy, result.operands) ||
289       parser.resolveOperand(addr, type, result.operands))
290     return failure();
291 
292   return success();
293 }
294 
295 ///===---------------------------------------------------------------------===//
296 /// LLVM::InvokeOp
297 ///===---------------------------------------------------------------------===//
298 
299 Optional<MutableOperandRange>
300 InvokeOp::getMutableSuccessorOperands(unsigned index) {
301   assert(index < getNumSuccessors() && "invalid successor index");
302   return index == 0 ? normalDestOperandsMutable() : unwindDestOperandsMutable();
303 }
304 
305 static LogicalResult verify(InvokeOp op) {
306   if (op.getNumResults() > 1)
307     return op.emitOpError("must have 0 or 1 result");
308 
309   Block *unwindDest = op.unwindDest();
310   if (unwindDest->empty())
311     return op.emitError(
312         "must have at least one operation in unwind destination");
313 
314   // In unwind destination, first operation must be LandingpadOp
315   if (!isa<LandingpadOp>(unwindDest->front()))
316     return op.emitError("first operation in unwind destination should be a "
317                         "llvm.landingpad operation");
318 
319   return success();
320 }
321 
322 static void printInvokeOp(OpAsmPrinter &p, InvokeOp op) {
323   auto callee = op.callee();
324   bool isDirect = callee.hasValue();
325 
326   p << op.getOperationName() << ' ';
327 
328   // Either function name or pointer
329   if (isDirect)
330     p.printSymbolName(callee.getValue());
331   else
332     p << op.getOperand(0);
333 
334   p << '(' << op.getOperands().drop_front(isDirect ? 0 : 1) << ')';
335   p << " to ";
336   p.printSuccessorAndUseList(op.normalDest(), op.normalDestOperands());
337   p << " unwind ";
338   p.printSuccessorAndUseList(op.unwindDest(), op.unwindDestOperands());
339 
340   p.printOptionalAttrDict(op.getAttrs(),
341                           {InvokeOp::getOperandSegmentSizeAttr(), "callee"});
342   p << " : ";
343   p.printFunctionalType(
344       llvm::drop_begin(op.getOperandTypes(), isDirect ? 0 : 1),
345       op.getResultTypes());
346 }
347 
348 /// <operation> ::= `llvm.invoke` (function-id | ssa-use) `(` ssa-use-list `)`
349 ///                  `to` bb-id (`[` ssa-use-and-type-list `]`)?
350 ///                  `unwind` bb-id (`[` ssa-use-and-type-list `]`)?
351 ///                  attribute-dict? `:` function-type
352 static ParseResult parseInvokeOp(OpAsmParser &parser, OperationState &result) {
353   SmallVector<OpAsmParser::OperandType, 8> operands;
354   FunctionType funcType;
355   SymbolRefAttr funcAttr;
356   llvm::SMLoc trailingTypeLoc;
357   Block *normalDest, *unwindDest;
358   SmallVector<Value, 4> normalOperands, unwindOperands;
359   Builder &builder = parser.getBuilder();
360 
361   // Parse an operand list that will, in practice, contain 0 or 1 operand.  In
362   // case of an indirect call, there will be 1 operand before `(`.  In case of a
363   // direct call, there will be no operands and the parser will stop at the
364   // function identifier without complaining.
365   if (parser.parseOperandList(operands))
366     return failure();
367   bool isDirect = operands.empty();
368 
369   // Optionally parse a function identifier.
370   if (isDirect && parser.parseAttribute(funcAttr, "callee", result.attributes))
371     return failure();
372 
373   if (parser.parseOperandList(operands, OpAsmParser::Delimiter::Paren) ||
374       parser.parseKeyword("to") ||
375       parser.parseSuccessorAndUseList(normalDest, normalOperands) ||
376       parser.parseKeyword("unwind") ||
377       parser.parseSuccessorAndUseList(unwindDest, unwindOperands) ||
378       parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
379       parser.getCurrentLocation(&trailingTypeLoc) || parser.parseType(funcType))
380     return failure();
381 
382   if (isDirect) {
383     // Make sure types match.
384     if (parser.resolveOperands(operands, funcType.getInputs(),
385                                parser.getNameLoc(), result.operands))
386       return failure();
387     result.addTypes(funcType.getResults());
388   } else {
389     // Construct the LLVM IR Dialect function type that the first operand
390     // should match.
391     if (funcType.getNumResults() > 1)
392       return parser.emitError(trailingTypeLoc,
393                               "expected function with 0 or 1 result");
394 
395     LLVM::LLVMType llvmResultType;
396     if (funcType.getNumResults() == 0) {
397       llvmResultType = LLVM::LLVMType::getVoidTy(builder.getContext());
398     } else {
399       llvmResultType = funcType.getResult(0).dyn_cast<LLVM::LLVMType>();
400       if (!llvmResultType)
401         return parser.emitError(trailingTypeLoc,
402                                 "expected result to have LLVM type");
403     }
404 
405     SmallVector<LLVM::LLVMType, 8> argTypes;
406     argTypes.reserve(funcType.getNumInputs());
407     for (Type ty : funcType.getInputs()) {
408       if (auto argType = ty.dyn_cast<LLVM::LLVMType>())
409         argTypes.push_back(argType);
410       else
411         return parser.emitError(trailingTypeLoc,
412                                 "expected LLVM types as inputs");
413     }
414 
415     auto llvmFuncType = LLVM::LLVMType::getFunctionTy(llvmResultType, argTypes,
416                                                       /*isVarArg=*/false);
417     auto wrappedFuncType = llvmFuncType.getPointerTo();
418 
419     auto funcArguments = llvm::makeArrayRef(operands).drop_front();
420 
421     // Make sure that the first operand (indirect callee) matches the wrapped
422     // LLVM IR function type, and that the types of the other call operands
423     // match the types of the function arguments.
424     if (parser.resolveOperand(operands[0], wrappedFuncType, result.operands) ||
425         parser.resolveOperands(funcArguments, funcType.getInputs(),
426                                parser.getNameLoc(), result.operands))
427       return failure();
428 
429     result.addTypes(llvmResultType);
430   }
431   result.addSuccessors({normalDest, unwindDest});
432   result.addOperands(normalOperands);
433   result.addOperands(unwindOperands);
434 
435   result.addAttribute(
436       InvokeOp::getOperandSegmentSizeAttr(),
437       builder.getI32VectorAttr({static_cast<int32_t>(operands.size()),
438                                 static_cast<int32_t>(normalOperands.size()),
439                                 static_cast<int32_t>(unwindOperands.size())}));
440   return success();
441 }
442 
443 ///===----------------------------------------------------------------------===//
444 /// Verifying/Printing/Parsing for LLVM::LandingpadOp.
445 ///===----------------------------------------------------------------------===//
446 
447 static LogicalResult verify(LandingpadOp op) {
448   Value value;
449   if (LLVMFuncOp func = op.getParentOfType<LLVMFuncOp>()) {
450     if (!func.personality().hasValue())
451       return op.emitError(
452           "llvm.landingpad needs to be in a function with a personality");
453   }
454 
455   if (!op.cleanup() && op.getOperands().empty())
456     return op.emitError("landingpad instruction expects at least one clause or "
457                         "cleanup attribute");
458 
459   for (unsigned idx = 0, ie = op.getNumOperands(); idx < ie; idx++) {
460     value = op.getOperand(idx);
461     bool isFilter = value.getType().cast<LLVMType>().isArrayTy();
462     if (isFilter) {
463       // FIXME: Verify filter clauses when arrays are appropriately handled
464     } else {
465       // catch - global addresses only.
466       // Bitcast ops should have global addresses as their args.
467       if (auto bcOp = value.getDefiningOp<BitcastOp>()) {
468         if (auto addrOp = bcOp.arg().getDefiningOp<AddressOfOp>())
469           continue;
470         return op.emitError("constant clauses expected")
471                    .attachNote(bcOp.getLoc())
472                << "global addresses expected as operand to "
473                   "bitcast used in clauses for landingpad";
474       }
475       // NullOp and AddressOfOp allowed
476       if (value.getDefiningOp<NullOp>())
477         continue;
478       if (value.getDefiningOp<AddressOfOp>())
479         continue;
480       return op.emitError("clause #")
481              << idx << " is not a known constant - null, addressof, bitcast";
482     }
483   }
484   return success();
485 }
486 
487 static void printLandingpadOp(OpAsmPrinter &p, LandingpadOp &op) {
488   p << op.getOperationName() << (op.cleanup() ? " cleanup " : " ");
489 
490   // Clauses
491   for (auto value : op.getOperands()) {
492     // Similar to llvm - if clause is an array type then it is filter
493     // clause else catch clause
494     bool isArrayTy = value.getType().cast<LLVMType>().isArrayTy();
495     p << '(' << (isArrayTy ? "filter " : "catch ") << value << " : "
496       << value.getType() << ") ";
497   }
498 
499   p.printOptionalAttrDict(op.getAttrs(), {"cleanup"});
500 
501   p << ": " << op.getType();
502 }
503 
504 /// <operation> ::= `llvm.landingpad` `cleanup`?
505 ///                 ((`catch` | `filter`) operand-type ssa-use)* attribute-dict?
506 static ParseResult parseLandingpadOp(OpAsmParser &parser,
507                                      OperationState &result) {
508   // Check for cleanup
509   if (succeeded(parser.parseOptionalKeyword("cleanup")))
510     result.addAttribute("cleanup", parser.getBuilder().getUnitAttr());
511 
512   // Parse clauses with types
513   while (succeeded(parser.parseOptionalLParen()) &&
514          (succeeded(parser.parseOptionalKeyword("filter")) ||
515           succeeded(parser.parseOptionalKeyword("catch")))) {
516     OpAsmParser::OperandType operand;
517     Type ty;
518     if (parser.parseOperand(operand) || parser.parseColon() ||
519         parser.parseType(ty) ||
520         parser.resolveOperand(operand, ty, result.operands) ||
521         parser.parseRParen())
522       return failure();
523   }
524 
525   Type type;
526   if (parser.parseColon() || parser.parseType(type))
527     return failure();
528 
529   result.addTypes(type);
530   return success();
531 }
532 
533 //===----------------------------------------------------------------------===//
534 // Printing/parsing for LLVM::CallOp.
535 //===----------------------------------------------------------------------===//
536 
537 static void printCallOp(OpAsmPrinter &p, CallOp &op) {
538   auto callee = op.callee();
539   bool isDirect = callee.hasValue();
540 
541   // Print the direct callee if present as a function attribute, or an indirect
542   // callee (first operand) otherwise.
543   p << op.getOperationName() << ' ';
544   if (isDirect)
545     p.printSymbolName(callee.getValue());
546   else
547     p << op.getOperand(0);
548 
549   auto args = op.getOperands().drop_front(isDirect ? 0 : 1);
550   p << '(' << args << ')';
551   p.printOptionalAttrDict(op.getAttrs(), {"callee"});
552 
553   // Reconstruct the function MLIR function type from operand and result types.
554   p << " : "
555     << FunctionType::get(args.getTypes(), op.getResultTypes(), op.getContext());
556 }
557 
558 // <operation> ::= `llvm.call` (function-id | ssa-use) `(` ssa-use-list `)`
559 //                 attribute-dict? `:` function-type
560 static ParseResult parseCallOp(OpAsmParser &parser, OperationState &result) {
561   SmallVector<OpAsmParser::OperandType, 8> operands;
562   Type type;
563   SymbolRefAttr funcAttr;
564   llvm::SMLoc trailingTypeLoc;
565 
566   // Parse an operand list that will, in practice, contain 0 or 1 operand.  In
567   // case of an indirect call, there will be 1 operand before `(`.  In case of a
568   // direct call, there will be no operands and the parser will stop at the
569   // function identifier without complaining.
570   if (parser.parseOperandList(operands))
571     return failure();
572   bool isDirect = operands.empty();
573 
574   // Optionally parse a function identifier.
575   if (isDirect)
576     if (parser.parseAttribute(funcAttr, "callee", result.attributes))
577       return failure();
578 
579   if (parser.parseOperandList(operands, OpAsmParser::Delimiter::Paren) ||
580       parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
581       parser.getCurrentLocation(&trailingTypeLoc) || parser.parseType(type))
582     return failure();
583 
584   auto funcType = type.dyn_cast<FunctionType>();
585   if (!funcType)
586     return parser.emitError(trailingTypeLoc, "expected function type");
587   if (isDirect) {
588     // Make sure types match.
589     if (parser.resolveOperands(operands, funcType.getInputs(),
590                                parser.getNameLoc(), result.operands))
591       return failure();
592     result.addTypes(funcType.getResults());
593   } else {
594     // Construct the LLVM IR Dialect function type that the first operand
595     // should match.
596     if (funcType.getNumResults() > 1)
597       return parser.emitError(trailingTypeLoc,
598                               "expected function with 0 or 1 result");
599 
600     Builder &builder = parser.getBuilder();
601     LLVM::LLVMType llvmResultType;
602     if (funcType.getNumResults() == 0) {
603       llvmResultType = LLVM::LLVMType::getVoidTy(builder.getContext());
604     } else {
605       llvmResultType = funcType.getResult(0).dyn_cast<LLVM::LLVMType>();
606       if (!llvmResultType)
607         return parser.emitError(trailingTypeLoc,
608                                 "expected result to have LLVM type");
609     }
610 
611     SmallVector<LLVM::LLVMType, 8> argTypes;
612     argTypes.reserve(funcType.getNumInputs());
613     for (int i = 0, e = funcType.getNumInputs(); i < e; ++i) {
614       auto argType = funcType.getInput(i).dyn_cast<LLVM::LLVMType>();
615       if (!argType)
616         return parser.emitError(trailingTypeLoc,
617                                 "expected LLVM types as inputs");
618       argTypes.push_back(argType);
619     }
620     auto llvmFuncType = LLVM::LLVMType::getFunctionTy(llvmResultType, argTypes,
621                                                       /*isVarArg=*/false);
622     auto wrappedFuncType = llvmFuncType.getPointerTo();
623 
624     auto funcArguments =
625         ArrayRef<OpAsmParser::OperandType>(operands).drop_front();
626 
627     // Make sure that the first operand (indirect callee) matches the wrapped
628     // LLVM IR function type, and that the types of the other call operands
629     // match the types of the function arguments.
630     if (parser.resolveOperand(operands[0], wrappedFuncType, result.operands) ||
631         parser.resolveOperands(funcArguments, funcType.getInputs(),
632                                parser.getNameLoc(), result.operands))
633       return failure();
634 
635     result.addTypes(llvmResultType);
636   }
637 
638   return success();
639 }
640 
641 //===----------------------------------------------------------------------===//
642 // Printing/parsing for LLVM::ExtractElementOp.
643 //===----------------------------------------------------------------------===//
644 // Expects vector to be of wrapped LLVM vector type and position to be of
645 // wrapped LLVM i32 type.
646 void LLVM::ExtractElementOp::build(OpBuilder &b, OperationState &result,
647                                    Value vector, Value position,
648                                    ArrayRef<NamedAttribute> attrs) {
649   auto wrappedVectorType = vector.getType().cast<LLVM::LLVMType>();
650   auto llvmType = wrappedVectorType.getVectorElementType();
651   build(b, result, llvmType, vector, position);
652   result.addAttributes(attrs);
653 }
654 
655 static void printExtractElementOp(OpAsmPrinter &p, ExtractElementOp &op) {
656   p << op.getOperationName() << ' ' << op.vector() << "[" << op.position()
657     << " : " << op.position().getType() << "]";
658   p.printOptionalAttrDict(op.getAttrs());
659   p << " : " << op.vector().getType();
660 }
661 
662 // <operation> ::= `llvm.extractelement` ssa-use `, ` ssa-use
663 //                 attribute-dict? `:` type
664 static ParseResult parseExtractElementOp(OpAsmParser &parser,
665                                          OperationState &result) {
666   llvm::SMLoc loc;
667   OpAsmParser::OperandType vector, position;
668   Type type, positionType;
669   if (parser.getCurrentLocation(&loc) || parser.parseOperand(vector) ||
670       parser.parseLSquare() || parser.parseOperand(position) ||
671       parser.parseColonType(positionType) || parser.parseRSquare() ||
672       parser.parseOptionalAttrDict(result.attributes) ||
673       parser.parseColonType(type) ||
674       parser.resolveOperand(vector, type, result.operands) ||
675       parser.resolveOperand(position, positionType, result.operands))
676     return failure();
677   auto wrappedVectorType = type.dyn_cast<LLVM::LLVMType>();
678   if (!wrappedVectorType || !wrappedVectorType.isVectorTy())
679     return parser.emitError(
680         loc, "expected LLVM IR dialect vector type for operand #1");
681   result.addTypes(wrappedVectorType.getVectorElementType());
682   return success();
683 }
684 
685 //===----------------------------------------------------------------------===//
686 // Printing/parsing for LLVM::ExtractValueOp.
687 //===----------------------------------------------------------------------===//
688 
689 static void printExtractValueOp(OpAsmPrinter &p, ExtractValueOp &op) {
690   p << op.getOperationName() << ' ' << op.container() << op.position();
691   p.printOptionalAttrDict(op.getAttrs(), {"position"});
692   p << " : " << op.container().getType();
693 }
694 
695 // Extract the type at `position` in the wrapped LLVM IR aggregate type
696 // `containerType`.  Position is an integer array attribute where each value
697 // is a zero-based position of the element in the aggregate type.  Return the
698 // resulting type wrapped in MLIR, or nullptr on error.
699 static LLVM::LLVMType getInsertExtractValueElementType(OpAsmParser &parser,
700                                                        Type containerType,
701                                                        ArrayAttr positionAttr,
702                                                        llvm::SMLoc attributeLoc,
703                                                        llvm::SMLoc typeLoc) {
704   auto wrappedContainerType = containerType.dyn_cast<LLVM::LLVMType>();
705   if (!wrappedContainerType)
706     return parser.emitError(typeLoc, "expected LLVM IR Dialect type"), nullptr;
707 
708   // Infer the element type from the structure type: iteratively step inside the
709   // type by taking the element type, indexed by the position attribute for
710   // structures.  Check the position index before accessing, it is supposed to
711   // be in bounds.
712   for (Attribute subAttr : positionAttr) {
713     auto positionElementAttr = subAttr.dyn_cast<IntegerAttr>();
714     if (!positionElementAttr)
715       return parser.emitError(attributeLoc,
716                               "expected an array of integer literals"),
717              nullptr;
718     int position = positionElementAttr.getInt();
719     if (wrappedContainerType.isArrayTy()) {
720       if (position < 0 || static_cast<unsigned>(position) >=
721                               wrappedContainerType.getArrayNumElements())
722         return parser.emitError(attributeLoc, "position out of bounds"),
723                nullptr;
724       wrappedContainerType = wrappedContainerType.getArrayElementType();
725     } else if (wrappedContainerType.isStructTy()) {
726       if (position < 0 || static_cast<unsigned>(position) >=
727                               wrappedContainerType.getStructNumElements())
728         return parser.emitError(attributeLoc, "position out of bounds"),
729                nullptr;
730       wrappedContainerType =
731           wrappedContainerType.getStructElementType(position);
732     } else {
733       return parser.emitError(typeLoc,
734                               "expected wrapped LLVM IR structure/array type"),
735              nullptr;
736     }
737   }
738   return wrappedContainerType;
739 }
740 
741 // <operation> ::= `llvm.extractvalue` ssa-use
742 //                 `[` integer-literal (`,` integer-literal)* `]`
743 //                 attribute-dict? `:` type
744 static ParseResult parseExtractValueOp(OpAsmParser &parser,
745                                        OperationState &result) {
746   OpAsmParser::OperandType container;
747   Type containerType;
748   ArrayAttr positionAttr;
749   llvm::SMLoc attributeLoc, trailingTypeLoc;
750 
751   if (parser.parseOperand(container) ||
752       parser.getCurrentLocation(&attributeLoc) ||
753       parser.parseAttribute(positionAttr, "position", result.attributes) ||
754       parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
755       parser.getCurrentLocation(&trailingTypeLoc) ||
756       parser.parseType(containerType) ||
757       parser.resolveOperand(container, containerType, result.operands))
758     return failure();
759 
760   auto elementType = getInsertExtractValueElementType(
761       parser, containerType, positionAttr, attributeLoc, trailingTypeLoc);
762   if (!elementType)
763     return failure();
764 
765   result.addTypes(elementType);
766   return success();
767 }
768 
769 //===----------------------------------------------------------------------===//
770 // Printing/parsing for LLVM::InsertElementOp.
771 //===----------------------------------------------------------------------===//
772 
773 static void printInsertElementOp(OpAsmPrinter &p, InsertElementOp &op) {
774   p << op.getOperationName() << ' ' << op.value() << ", " << op.vector() << "["
775     << op.position() << " : " << op.position().getType() << "]";
776   p.printOptionalAttrDict(op.getAttrs());
777   p << " : " << op.vector().getType();
778 }
779 
780 // <operation> ::= `llvm.insertelement` ssa-use `,` ssa-use `,` ssa-use
781 //                 attribute-dict? `:` type
782 static ParseResult parseInsertElementOp(OpAsmParser &parser,
783                                         OperationState &result) {
784   llvm::SMLoc loc;
785   OpAsmParser::OperandType vector, value, position;
786   Type vectorType, positionType;
787   if (parser.getCurrentLocation(&loc) || parser.parseOperand(value) ||
788       parser.parseComma() || parser.parseOperand(vector) ||
789       parser.parseLSquare() || parser.parseOperand(position) ||
790       parser.parseColonType(positionType) || parser.parseRSquare() ||
791       parser.parseOptionalAttrDict(result.attributes) ||
792       parser.parseColonType(vectorType))
793     return failure();
794 
795   auto wrappedVectorType = vectorType.dyn_cast<LLVM::LLVMType>();
796   if (!wrappedVectorType || !wrappedVectorType.isVectorTy())
797     return parser.emitError(
798         loc, "expected LLVM IR dialect vector type for operand #1");
799   auto valueType = wrappedVectorType.getVectorElementType();
800   if (!valueType)
801     return failure();
802 
803   if (parser.resolveOperand(vector, vectorType, result.operands) ||
804       parser.resolveOperand(value, valueType, result.operands) ||
805       parser.resolveOperand(position, positionType, result.operands))
806     return failure();
807 
808   result.addTypes(vectorType);
809   return success();
810 }
811 
812 //===----------------------------------------------------------------------===//
813 // Printing/parsing for LLVM::InsertValueOp.
814 //===----------------------------------------------------------------------===//
815 
816 static void printInsertValueOp(OpAsmPrinter &p, InsertValueOp &op) {
817   p << op.getOperationName() << ' ' << op.value() << ", " << op.container()
818     << op.position();
819   p.printOptionalAttrDict(op.getAttrs(), {"position"});
820   p << " : " << op.container().getType();
821 }
822 
823 // <operation> ::= `llvm.insertvaluevalue` ssa-use `,` ssa-use
824 //                 `[` integer-literal (`,` integer-literal)* `]`
825 //                 attribute-dict? `:` type
826 static ParseResult parseInsertValueOp(OpAsmParser &parser,
827                                       OperationState &result) {
828   OpAsmParser::OperandType container, value;
829   Type containerType;
830   ArrayAttr positionAttr;
831   llvm::SMLoc attributeLoc, trailingTypeLoc;
832 
833   if (parser.parseOperand(value) || parser.parseComma() ||
834       parser.parseOperand(container) ||
835       parser.getCurrentLocation(&attributeLoc) ||
836       parser.parseAttribute(positionAttr, "position", result.attributes) ||
837       parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
838       parser.getCurrentLocation(&trailingTypeLoc) ||
839       parser.parseType(containerType))
840     return failure();
841 
842   auto valueType = getInsertExtractValueElementType(
843       parser, containerType, positionAttr, attributeLoc, trailingTypeLoc);
844   if (!valueType)
845     return failure();
846 
847   if (parser.resolveOperand(container, containerType, result.operands) ||
848       parser.resolveOperand(value, valueType, result.operands))
849     return failure();
850 
851   result.addTypes(containerType);
852   return success();
853 }
854 
855 //===----------------------------------------------------------------------===//
856 // Printing/parsing for LLVM::ReturnOp.
857 //===----------------------------------------------------------------------===//
858 
859 static void printReturnOp(OpAsmPrinter &p, ReturnOp &op) {
860   p << op.getOperationName();
861   p.printOptionalAttrDict(op.getAttrs());
862   assert(op.getNumOperands() <= 1);
863 
864   if (op.getNumOperands() == 0)
865     return;
866 
867   p << ' ' << op.getOperand(0) << " : " << op.getOperand(0).getType();
868 }
869 
870 // <operation> ::= `llvm.return` ssa-use-list attribute-dict? `:`
871 //                 type-list-no-parens
872 static ParseResult parseReturnOp(OpAsmParser &parser, OperationState &result) {
873   SmallVector<OpAsmParser::OperandType, 1> operands;
874   Type type;
875 
876   if (parser.parseOperandList(operands) ||
877       parser.parseOptionalAttrDict(result.attributes))
878     return failure();
879   if (operands.empty())
880     return success();
881 
882   if (parser.parseColonType(type) ||
883       parser.resolveOperand(operands[0], type, result.operands))
884     return failure();
885   return success();
886 }
887 
888 //===----------------------------------------------------------------------===//
889 // Verifier for LLVM::AddressOfOp.
890 //===----------------------------------------------------------------------===//
891 
892 template <typename OpTy>
893 static OpTy lookupSymbolInModule(Operation *parent, StringRef name) {
894   Operation *module = parent;
895   while (module && !satisfiesLLVMModule(module))
896     module = module->getParentOp();
897   assert(module && "unexpected operation outside of a module");
898   return dyn_cast_or_null<OpTy>(
899       mlir::SymbolTable::lookupSymbolIn(module, name));
900 }
901 
902 GlobalOp AddressOfOp::getGlobal() {
903   return lookupSymbolInModule<LLVM::GlobalOp>(getParentOp(), global_name());
904 }
905 
906 LLVMFuncOp AddressOfOp::getFunction() {
907   return lookupSymbolInModule<LLVM::LLVMFuncOp>(getParentOp(), global_name());
908 }
909 
910 static LogicalResult verify(AddressOfOp op) {
911   auto global = op.getGlobal();
912   auto function = op.getFunction();
913   if (!global && !function)
914     return op.emitOpError(
915         "must reference a global defined by 'llvm.mlir.global' or 'llvm.func'");
916 
917   if (global &&
918       global.getType().getPointerTo(global.addr_space().getZExtValue()) !=
919           op.getResult().getType())
920     return op.emitOpError(
921         "the type must be a pointer to the type of the referenced global");
922 
923   if (function && function.getType().getPointerTo() != op.getResult().getType())
924     return op.emitOpError(
925         "the type must be a pointer to the type of the referenced function");
926 
927   return success();
928 }
929 
930 //===----------------------------------------------------------------------===//
931 // Builder, printer and verifier for LLVM::GlobalOp.
932 //===----------------------------------------------------------------------===//
933 
934 /// Returns the name used for the linkage attribute. This *must* correspond to
935 /// the name of the attribute in ODS.
936 static StringRef getLinkageAttrName() { return "linkage"; }
937 
938 void GlobalOp::build(OpBuilder &builder, OperationState &result, LLVMType type,
939                      bool isConstant, Linkage linkage, StringRef name,
940                      Attribute value, unsigned addrSpace,
941                      ArrayRef<NamedAttribute> attrs) {
942   result.addAttribute(SymbolTable::getSymbolAttrName(),
943                       builder.getStringAttr(name));
944   result.addAttribute("type", TypeAttr::get(type));
945   if (isConstant)
946     result.addAttribute("constant", builder.getUnitAttr());
947   if (value)
948     result.addAttribute("value", value);
949   result.addAttribute(getLinkageAttrName(),
950                       builder.getI64IntegerAttr(static_cast<int64_t>(linkage)));
951   if (addrSpace != 0)
952     result.addAttribute("addr_space", builder.getI32IntegerAttr(addrSpace));
953   result.attributes.append(attrs.begin(), attrs.end());
954   result.addRegion();
955 }
956 
957 static void printGlobalOp(OpAsmPrinter &p, GlobalOp op) {
958   p << op.getOperationName() << ' ' << stringifyLinkage(op.linkage()) << ' ';
959   if (op.constant())
960     p << "constant ";
961   p.printSymbolName(op.sym_name());
962   p << '(';
963   if (auto value = op.getValueOrNull())
964     p.printAttribute(value);
965   p << ')';
966   p.printOptionalAttrDict(op.getAttrs(),
967                           {SymbolTable::getSymbolAttrName(), "type", "constant",
968                            "value", getLinkageAttrName()});
969 
970   // Print the trailing type unless it's a string global.
971   if (op.getValueOrNull().dyn_cast_or_null<StringAttr>())
972     return;
973   p << " : " << op.type();
974 
975   Region &initializer = op.getInitializerRegion();
976   if (!initializer.empty())
977     p.printRegion(initializer, /*printEntryBlockArgs=*/false);
978 }
979 
980 //===----------------------------------------------------------------------===//
981 // Verifier for LLVM::DialectCastOp.
982 //===----------------------------------------------------------------------===//
983 
984 static LogicalResult verify(DialectCastOp op) {
985   auto verifyMLIRCastType = [&op](Type type) -> LogicalResult {
986     if (auto llvmType = type.dyn_cast<LLVM::LLVMType>()) {
987       if (llvmType.isVectorTy())
988         llvmType = llvmType.getVectorElementType();
989       if (llvmType.isIntegerTy() || llvmType.isBFloatTy() ||
990           llvmType.isHalfTy() || llvmType.isFloatTy() ||
991           llvmType.isDoubleTy()) {
992         return success();
993       }
994       return op.emitOpError("type must be non-index integer types, float "
995                             "types, or vector of mentioned types.");
996     }
997     if (auto vectorType = type.dyn_cast<VectorType>()) {
998       if (vectorType.getShape().size() > 1)
999         return op.emitOpError("only 1-d vector is allowed");
1000       type = vectorType.getElementType();
1001     }
1002     if (type.isSignlessIntOrFloat())
1003       return success();
1004     // Note that memrefs are not supported. We currently don't have a use case
1005     // for it, but even if we do, there are challenges:
1006     // * if we allow memrefs to cast from/to memref descriptors, then the
1007     // semantics of the cast op depends on the implementation detail of the
1008     // descriptor.
1009     // * if we allow memrefs to cast from/to bare pointers, some users might
1010     // alternatively want metadata that only present in the descriptor.
1011     //
1012     // TODO: re-evaluate the memref cast design when it's needed.
1013     return op.emitOpError("type must be non-index integer types, float types, "
1014                           "or vector of mentioned types.");
1015   };
1016   return failure(failed(verifyMLIRCastType(op.in().getType())) ||
1017                  failed(verifyMLIRCastType(op.getType())));
1018 }
1019 
1020 // Parses one of the keywords provided in the list `keywords` and returns the
1021 // position of the parsed keyword in the list. If none of the keywords from the
1022 // list is parsed, returns -1.
1023 static int parseOptionalKeywordAlternative(OpAsmParser &parser,
1024                                            ArrayRef<StringRef> keywords) {
1025   for (auto en : llvm::enumerate(keywords)) {
1026     if (succeeded(parser.parseOptionalKeyword(en.value())))
1027       return en.index();
1028   }
1029   return -1;
1030 }
1031 
1032 namespace {
1033 template <typename Ty> struct EnumTraits {};
1034 
1035 #define REGISTER_ENUM_TYPE(Ty)                                                 \
1036   template <> struct EnumTraits<Ty> {                                          \
1037     static StringRef stringify(Ty value) { return stringify##Ty(value); }      \
1038     static unsigned getMaxEnumVal() { return getMaxEnumValFor##Ty(); }         \
1039   }
1040 
1041 REGISTER_ENUM_TYPE(Linkage);
1042 } // end namespace
1043 
1044 template <typename EnumTy>
1045 static ParseResult parseOptionalLLVMKeyword(OpAsmParser &parser,
1046                                             OperationState &result,
1047                                             StringRef name) {
1048   SmallVector<StringRef, 10> names;
1049   for (unsigned i = 0, e = getMaxEnumValForLinkage(); i <= e; ++i)
1050     names.push_back(EnumTraits<EnumTy>::stringify(static_cast<EnumTy>(i)));
1051 
1052   int index = parseOptionalKeywordAlternative(parser, names);
1053   if (index == -1)
1054     return failure();
1055   result.addAttribute(name, parser.getBuilder().getI64IntegerAttr(index));
1056   return success();
1057 }
1058 
1059 // operation ::= `llvm.mlir.global` linkage? `constant`? `@` identifier
1060 //               `(` attribute? `)` attribute-list? (`:` type)? region?
1061 //
1062 // The type can be omitted for string attributes, in which case it will be
1063 // inferred from the value of the string as [strlen(value) x i8].
1064 static ParseResult parseGlobalOp(OpAsmParser &parser, OperationState &result) {
1065   if (failed(parseOptionalLLVMKeyword<Linkage>(parser, result,
1066                                                getLinkageAttrName())))
1067     result.addAttribute(getLinkageAttrName(),
1068                         parser.getBuilder().getI64IntegerAttr(
1069                             static_cast<int64_t>(LLVM::Linkage::External)));
1070 
1071   if (succeeded(parser.parseOptionalKeyword("constant")))
1072     result.addAttribute("constant", parser.getBuilder().getUnitAttr());
1073 
1074   StringAttr name;
1075   if (parser.parseSymbolName(name, SymbolTable::getSymbolAttrName(),
1076                              result.attributes) ||
1077       parser.parseLParen())
1078     return failure();
1079 
1080   Attribute value;
1081   if (parser.parseOptionalRParen()) {
1082     if (parser.parseAttribute(value, "value", result.attributes) ||
1083         parser.parseRParen())
1084       return failure();
1085   }
1086 
1087   SmallVector<Type, 1> types;
1088   if (parser.parseOptionalAttrDict(result.attributes) ||
1089       parser.parseOptionalColonTypeList(types))
1090     return failure();
1091 
1092   if (types.size() > 1)
1093     return parser.emitError(parser.getNameLoc(), "expected zero or one type");
1094 
1095   Region &initRegion = *result.addRegion();
1096   if (types.empty()) {
1097     if (auto strAttr = value.dyn_cast_or_null<StringAttr>()) {
1098       MLIRContext *context = parser.getBuilder().getContext();
1099       auto arrayType = LLVM::LLVMType::getArrayTy(
1100           LLVM::LLVMType::getInt8Ty(context), strAttr.getValue().size());
1101       types.push_back(arrayType);
1102     } else {
1103       return parser.emitError(parser.getNameLoc(),
1104                               "type can only be omitted for string globals");
1105     }
1106   } else if (parser.parseOptionalRegion(initRegion, /*arguments=*/{},
1107                                         /*argTypes=*/{})) {
1108     return failure();
1109   }
1110 
1111   result.addAttribute("type", TypeAttr::get(types[0]));
1112   return success();
1113 }
1114 
1115 static LogicalResult verify(GlobalOp op) {
1116   if (!LLVMType::isValidPointerElementType(op.getType()))
1117     return op.emitOpError(
1118         "expects type to be a valid element type for an LLVM pointer");
1119   if (op.getParentOp() && !satisfiesLLVMModule(op.getParentOp()))
1120     return op.emitOpError("must appear at the module level");
1121 
1122   if (auto strAttr = op.getValueOrNull().dyn_cast_or_null<StringAttr>()) {
1123     auto type = op.getType();
1124     if (!type.isArrayTy() || !type.getArrayElementType().isIntegerTy(8) ||
1125         type.getArrayNumElements() != strAttr.getValue().size())
1126       return op.emitOpError(
1127           "requires an i8 array type of the length equal to that of the string "
1128           "attribute");
1129   }
1130 
1131   if (Block *b = op.getInitializerBlock()) {
1132     ReturnOp ret = cast<ReturnOp>(b->getTerminator());
1133     if (ret.operand_type_begin() == ret.operand_type_end())
1134       return op.emitOpError("initializer region cannot return void");
1135     if (*ret.operand_type_begin() != op.getType())
1136       return op.emitOpError("initializer region type ")
1137              << *ret.operand_type_begin() << " does not match global type "
1138              << op.getType();
1139 
1140     if (op.getValueOrNull())
1141       return op.emitOpError("cannot have both initializer value and region");
1142   }
1143   return success();
1144 }
1145 
1146 //===----------------------------------------------------------------------===//
1147 // Printing/parsing for LLVM::ShuffleVectorOp.
1148 //===----------------------------------------------------------------------===//
1149 // Expects vector to be of wrapped LLVM vector type and position to be of
1150 // wrapped LLVM i32 type.
1151 void LLVM::ShuffleVectorOp::build(OpBuilder &b, OperationState &result,
1152                                   Value v1, Value v2, ArrayAttr mask,
1153                                   ArrayRef<NamedAttribute> attrs) {
1154   auto wrappedContainerType1 = v1.getType().cast<LLVM::LLVMType>();
1155   auto vType = LLVMType::getVectorTy(
1156       wrappedContainerType1.getVectorElementType(), mask.size());
1157   build(b, result, vType, v1, v2, mask);
1158   result.addAttributes(attrs);
1159 }
1160 
1161 static void printShuffleVectorOp(OpAsmPrinter &p, ShuffleVectorOp &op) {
1162   p << op.getOperationName() << ' ' << op.v1() << ", " << op.v2() << " "
1163     << op.mask();
1164   p.printOptionalAttrDict(op.getAttrs(), {"mask"});
1165   p << " : " << op.v1().getType() << ", " << op.v2().getType();
1166 }
1167 
1168 // <operation> ::= `llvm.shufflevector` ssa-use `, ` ssa-use
1169 //                 `[` integer-literal (`,` integer-literal)* `]`
1170 //                 attribute-dict? `:` type
1171 static ParseResult parseShuffleVectorOp(OpAsmParser &parser,
1172                                         OperationState &result) {
1173   llvm::SMLoc loc;
1174   OpAsmParser::OperandType v1, v2;
1175   ArrayAttr maskAttr;
1176   Type typeV1, typeV2;
1177   if (parser.getCurrentLocation(&loc) || parser.parseOperand(v1) ||
1178       parser.parseComma() || parser.parseOperand(v2) ||
1179       parser.parseAttribute(maskAttr, "mask", result.attributes) ||
1180       parser.parseOptionalAttrDict(result.attributes) ||
1181       parser.parseColonType(typeV1) || parser.parseComma() ||
1182       parser.parseType(typeV2) ||
1183       parser.resolveOperand(v1, typeV1, result.operands) ||
1184       parser.resolveOperand(v2, typeV2, result.operands))
1185     return failure();
1186   auto wrappedContainerType1 = typeV1.dyn_cast<LLVM::LLVMType>();
1187   if (!wrappedContainerType1 || !wrappedContainerType1.isVectorTy())
1188     return parser.emitError(
1189         loc, "expected LLVM IR dialect vector type for operand #1");
1190   auto vType = LLVMType::getVectorTy(
1191       wrappedContainerType1.getVectorElementType(), maskAttr.size());
1192   result.addTypes(vType);
1193   return success();
1194 }
1195 
1196 //===----------------------------------------------------------------------===//
1197 // Implementations for LLVM::LLVMFuncOp.
1198 //===----------------------------------------------------------------------===//
1199 
1200 // Add the entry block to the function.
1201 Block *LLVMFuncOp::addEntryBlock() {
1202   assert(empty() && "function already has an entry block");
1203   assert(!isVarArg() && "unimplemented: non-external variadic functions");
1204 
1205   auto *entry = new Block;
1206   push_back(entry);
1207 
1208   LLVMType type = getType();
1209   for (unsigned i = 0, e = type.getFunctionNumParams(); i < e; ++i)
1210     entry->addArgument(type.getFunctionParamType(i));
1211   return entry;
1212 }
1213 
1214 void LLVMFuncOp::build(OpBuilder &builder, OperationState &result,
1215                        StringRef name, LLVMType type, LLVM::Linkage linkage,
1216                        ArrayRef<NamedAttribute> attrs,
1217                        ArrayRef<MutableDictionaryAttr> argAttrs) {
1218   result.addRegion();
1219   result.addAttribute(SymbolTable::getSymbolAttrName(),
1220                       builder.getStringAttr(name));
1221   result.addAttribute("type", TypeAttr::get(type));
1222   result.addAttribute(getLinkageAttrName(),
1223                       builder.getI64IntegerAttr(static_cast<int64_t>(linkage)));
1224   result.attributes.append(attrs.begin(), attrs.end());
1225   if (argAttrs.empty())
1226     return;
1227 
1228   unsigned numInputs = type.getFunctionNumParams();
1229   assert(numInputs == argAttrs.size() &&
1230          "expected as many argument attribute lists as arguments");
1231   SmallString<8> argAttrName;
1232   for (unsigned i = 0; i < numInputs; ++i)
1233     if (auto argDict = argAttrs[i].getDictionary(builder.getContext()))
1234       result.addAttribute(getArgAttrName(i, argAttrName), argDict);
1235 }
1236 
1237 // Builds an LLVM function type from the given lists of input and output types.
1238 // Returns a null type if any of the types provided are non-LLVM types, or if
1239 // there is more than one output type.
1240 static Type buildLLVMFunctionType(OpAsmParser &parser, llvm::SMLoc loc,
1241                                   ArrayRef<Type> inputs, ArrayRef<Type> outputs,
1242                                   impl::VariadicFlag variadicFlag) {
1243   Builder &b = parser.getBuilder();
1244   if (outputs.size() > 1) {
1245     parser.emitError(loc, "failed to construct function type: expected zero or "
1246                           "one function result");
1247     return {};
1248   }
1249 
1250   // Convert inputs to LLVM types, exit early on error.
1251   SmallVector<LLVMType, 4> llvmInputs;
1252   for (auto t : inputs) {
1253     auto llvmTy = t.dyn_cast<LLVMType>();
1254     if (!llvmTy) {
1255       parser.emitError(loc, "failed to construct function type: expected LLVM "
1256                             "type for function arguments");
1257       return {};
1258     }
1259     llvmInputs.push_back(llvmTy);
1260   }
1261 
1262   // No output is denoted as "void" in LLVM type system.
1263   LLVMType llvmOutput = outputs.empty() ? LLVMType::getVoidTy(b.getContext())
1264                                         : outputs.front().dyn_cast<LLVMType>();
1265   if (!llvmOutput) {
1266     parser.emitError(loc, "failed to construct function type: expected LLVM "
1267                           "type for function results");
1268     return {};
1269   }
1270   return LLVMType::getFunctionTy(llvmOutput, llvmInputs,
1271                                  variadicFlag.isVariadic());
1272 }
1273 
1274 // Parses an LLVM function.
1275 //
1276 // operation ::= `llvm.func` linkage? function-signature function-attributes?
1277 //               function-body
1278 //
1279 static ParseResult parseLLVMFuncOp(OpAsmParser &parser,
1280                                    OperationState &result) {
1281   // Default to external linkage if no keyword is provided.
1282   if (failed(parseOptionalLLVMKeyword<Linkage>(parser, result,
1283                                                getLinkageAttrName())))
1284     result.addAttribute(getLinkageAttrName(),
1285                         parser.getBuilder().getI64IntegerAttr(
1286                             static_cast<int64_t>(LLVM::Linkage::External)));
1287 
1288   StringAttr nameAttr;
1289   SmallVector<OpAsmParser::OperandType, 8> entryArgs;
1290   SmallVector<NamedAttrList, 1> argAttrs;
1291   SmallVector<NamedAttrList, 1> resultAttrs;
1292   SmallVector<Type, 8> argTypes;
1293   SmallVector<Type, 4> resultTypes;
1294   bool isVariadic;
1295 
1296   auto signatureLocation = parser.getCurrentLocation();
1297   if (parser.parseSymbolName(nameAttr, SymbolTable::getSymbolAttrName(),
1298                              result.attributes) ||
1299       impl::parseFunctionSignature(parser, /*allowVariadic=*/true, entryArgs,
1300                                    argTypes, argAttrs, isVariadic, resultTypes,
1301                                    resultAttrs))
1302     return failure();
1303 
1304   auto type =
1305       buildLLVMFunctionType(parser, signatureLocation, argTypes, resultTypes,
1306                             impl::VariadicFlag(isVariadic));
1307   if (!type)
1308     return failure();
1309   result.addAttribute(impl::getTypeAttrName(), TypeAttr::get(type));
1310 
1311   if (failed(parser.parseOptionalAttrDictWithKeyword(result.attributes)))
1312     return failure();
1313   impl::addArgAndResultAttrs(parser.getBuilder(), result, argAttrs,
1314                              resultAttrs);
1315 
1316   auto *body = result.addRegion();
1317   return parser.parseOptionalRegion(
1318       *body, entryArgs, entryArgs.empty() ? ArrayRef<Type>() : argTypes);
1319 }
1320 
1321 // Print the LLVMFuncOp. Collects argument and result types and passes them to
1322 // helper functions. Drops "void" result since it cannot be parsed back. Skips
1323 // the external linkage since it is the default value.
1324 static void printLLVMFuncOp(OpAsmPrinter &p, LLVMFuncOp op) {
1325   p << op.getOperationName() << ' ';
1326   if (op.linkage() != LLVM::Linkage::External)
1327     p << stringifyLinkage(op.linkage()) << ' ';
1328   p.printSymbolName(op.getName());
1329 
1330   LLVMType fnType = op.getType();
1331   SmallVector<Type, 8> argTypes;
1332   SmallVector<Type, 1> resTypes;
1333   argTypes.reserve(fnType.getFunctionNumParams());
1334   for (unsigned i = 0, e = fnType.getFunctionNumParams(); i < e; ++i)
1335     argTypes.push_back(fnType.getFunctionParamType(i));
1336 
1337   LLVMType returnType = fnType.getFunctionResultType();
1338   if (!returnType.isVoidTy())
1339     resTypes.push_back(returnType);
1340 
1341   impl::printFunctionSignature(p, op, argTypes, op.isVarArg(), resTypes);
1342   impl::printFunctionAttributes(p, op, argTypes.size(), resTypes.size(),
1343                                 {getLinkageAttrName()});
1344 
1345   // Print the body if this is not an external function.
1346   Region &body = op.body();
1347   if (!body.empty())
1348     p.printRegion(body, /*printEntryBlockArgs=*/false,
1349                   /*printBlockTerminators=*/true);
1350 }
1351 
1352 // Hook for OpTrait::FunctionLike, called after verifying that the 'type'
1353 // attribute is present.  This can check for preconditions of the
1354 // getNumArguments hook not failing.
1355 LogicalResult LLVMFuncOp::verifyType() {
1356   auto llvmType = getTypeAttr().getValue().dyn_cast_or_null<LLVMType>();
1357   if (!llvmType || !llvmType.isFunctionTy())
1358     return emitOpError("requires '" + getTypeAttrName() +
1359                        "' attribute of wrapped LLVM function type");
1360 
1361   return success();
1362 }
1363 
1364 // Hook for OpTrait::FunctionLike, returns the number of function arguments.
1365 // Depends on the type attribute being correct as checked by verifyType
1366 unsigned LLVMFuncOp::getNumFuncArguments() {
1367   return getType().getFunctionNumParams();
1368 }
1369 
1370 // Hook for OpTrait::FunctionLike, returns the number of function results.
1371 // Depends on the type attribute being correct as checked by verifyType
1372 unsigned LLVMFuncOp::getNumFuncResults() {
1373   // We model LLVM functions that return void as having zero results,
1374   // and all others as having one result.
1375   // If we modeled a void return as one result, then it would be possible to
1376   // attach an MLIR result attribute to it, and it isn't clear what semantics we
1377   // would assign to that.
1378   if (getType().getFunctionResultType().isVoidTy())
1379     return 0;
1380   return 1;
1381 }
1382 
1383 // Verifies LLVM- and implementation-specific properties of the LLVM func Op:
1384 // - functions don't have 'common' linkage
1385 // - external functions have 'external' or 'extern_weak' linkage;
1386 // - vararg is (currently) only supported for external functions;
1387 // - entry block arguments are of LLVM types and match the function signature.
1388 static LogicalResult verify(LLVMFuncOp op) {
1389   if (op.linkage() == LLVM::Linkage::Common)
1390     return op.emitOpError()
1391            << "functions cannot have '"
1392            << stringifyLinkage(LLVM::Linkage::Common) << "' linkage";
1393 
1394   if (op.isExternal()) {
1395     if (op.linkage() != LLVM::Linkage::External &&
1396         op.linkage() != LLVM::Linkage::ExternWeak)
1397       return op.emitOpError()
1398              << "external functions must have '"
1399              << stringifyLinkage(LLVM::Linkage::External) << "' or '"
1400              << stringifyLinkage(LLVM::Linkage::ExternWeak) << "' linkage";
1401     return success();
1402   }
1403 
1404   if (op.isVarArg())
1405     return op.emitOpError("only external functions can be variadic");
1406 
1407   unsigned numArguments = op.getType().getFunctionNumParams();
1408   Block &entryBlock = op.front();
1409   for (unsigned i = 0; i < numArguments; ++i) {
1410     Type argType = entryBlock.getArgument(i).getType();
1411     auto argLLVMType = argType.dyn_cast<LLVMType>();
1412     if (!argLLVMType)
1413       return op.emitOpError("entry block argument #")
1414              << i << " is not of LLVM type";
1415     if (op.getType().getFunctionParamType(i) != argLLVMType)
1416       return op.emitOpError("the type of entry block argument #")
1417              << i << " does not match the function signature";
1418   }
1419 
1420   return success();
1421 }
1422 
1423 //===----------------------------------------------------------------------===//
1424 // Verification for LLVM::NullOp.
1425 //===----------------------------------------------------------------------===//
1426 
1427 // Only LLVM pointer types are supported.
1428 static LogicalResult verify(LLVM::NullOp op) {
1429   auto llvmType = op.getType().dyn_cast<LLVM::LLVMType>();
1430   if (!llvmType || !llvmType.isPointerTy())
1431     return op.emitOpError("expected LLVM IR pointer type");
1432   return success();
1433 }
1434 
1435 //===----------------------------------------------------------------------===//
1436 // Verification for LLVM::ConstantOp.
1437 //===----------------------------------------------------------------------===//
1438 
1439 static LogicalResult verify(LLVM::ConstantOp op) {
1440   if (!(op.value().isa<IntegerAttr>() || op.value().isa<FloatAttr>() ||
1441         op.value().isa<ElementsAttr>() || op.value().isa<StringAttr>()))
1442     return op.emitOpError()
1443            << "only supports integer, float, string or elements attributes";
1444   return success();
1445 }
1446 
1447 //===----------------------------------------------------------------------===//
1448 // Utility functions for parsing atomic ops
1449 //===----------------------------------------------------------------------===//
1450 
1451 // Helper function to parse a keyword into the specified attribute named by
1452 // `attrName`. The keyword must match one of the string values defined by the
1453 // AtomicBinOp enum. The resulting I64 attribute is added to the `result`
1454 // state.
1455 static ParseResult parseAtomicBinOp(OpAsmParser &parser, OperationState &result,
1456                                     StringRef attrName) {
1457   llvm::SMLoc loc;
1458   StringRef keyword;
1459   if (parser.getCurrentLocation(&loc) || parser.parseKeyword(&keyword))
1460     return failure();
1461 
1462   // Replace the keyword `keyword` with an integer attribute.
1463   auto kind = symbolizeAtomicBinOp(keyword);
1464   if (!kind) {
1465     return parser.emitError(loc)
1466            << "'" << keyword << "' is an incorrect value of the '" << attrName
1467            << "' attribute";
1468   }
1469 
1470   auto value = static_cast<int64_t>(kind.getValue());
1471   auto attr = parser.getBuilder().getI64IntegerAttr(value);
1472   result.addAttribute(attrName, attr);
1473 
1474   return success();
1475 }
1476 
1477 // Helper function to parse a keyword into the specified attribute named by
1478 // `attrName`. The keyword must match one of the string values defined by the
1479 // AtomicOrdering enum. The resulting I64 attribute is added to the `result`
1480 // state.
1481 static ParseResult parseAtomicOrdering(OpAsmParser &parser,
1482                                        OperationState &result,
1483                                        StringRef attrName) {
1484   llvm::SMLoc loc;
1485   StringRef ordering;
1486   if (parser.getCurrentLocation(&loc) || parser.parseKeyword(&ordering))
1487     return failure();
1488 
1489   // Replace the keyword `ordering` with an integer attribute.
1490   auto kind = symbolizeAtomicOrdering(ordering);
1491   if (!kind) {
1492     return parser.emitError(loc)
1493            << "'" << ordering << "' is an incorrect value of the '" << attrName
1494            << "' attribute";
1495   }
1496 
1497   auto value = static_cast<int64_t>(kind.getValue());
1498   auto attr = parser.getBuilder().getI64IntegerAttr(value);
1499   result.addAttribute(attrName, attr);
1500 
1501   return success();
1502 }
1503 
1504 //===----------------------------------------------------------------------===//
1505 // Printer, parser and verifier for LLVM::AtomicRMWOp.
1506 //===----------------------------------------------------------------------===//
1507 
1508 static void printAtomicRMWOp(OpAsmPrinter &p, AtomicRMWOp &op) {
1509   p << op.getOperationName() << ' ' << stringifyAtomicBinOp(op.bin_op()) << ' '
1510     << op.ptr() << ", " << op.val() << ' '
1511     << stringifyAtomicOrdering(op.ordering()) << ' ';
1512   p.printOptionalAttrDict(op.getAttrs(), {"bin_op", "ordering"});
1513   p << " : " << op.res().getType();
1514 }
1515 
1516 // <operation> ::= `llvm.atomicrmw` keyword ssa-use `,` ssa-use keyword
1517 //                 attribute-dict? `:` type
1518 static ParseResult parseAtomicRMWOp(OpAsmParser &parser,
1519                                     OperationState &result) {
1520   LLVMType type;
1521   OpAsmParser::OperandType ptr, val;
1522   if (parseAtomicBinOp(parser, result, "bin_op") || parser.parseOperand(ptr) ||
1523       parser.parseComma() || parser.parseOperand(val) ||
1524       parseAtomicOrdering(parser, result, "ordering") ||
1525       parser.parseOptionalAttrDict(result.attributes) ||
1526       parser.parseColonType(type) ||
1527       parser.resolveOperand(ptr, type.getPointerTo(), result.operands) ||
1528       parser.resolveOperand(val, type, result.operands))
1529     return failure();
1530 
1531   result.addTypes(type);
1532   return success();
1533 }
1534 
1535 static LogicalResult verify(AtomicRMWOp op) {
1536   auto ptrType = op.ptr().getType().cast<LLVM::LLVMType>();
1537   if (!ptrType.isPointerTy())
1538     return op.emitOpError("expected LLVM IR pointer type for operand #0");
1539   auto valType = op.val().getType().cast<LLVM::LLVMType>();
1540   if (valType != ptrType.getPointerElementTy())
1541     return op.emitOpError("expected LLVM IR element type for operand #0 to "
1542                           "match type for operand #1");
1543   auto resType = op.res().getType().cast<LLVM::LLVMType>();
1544   if (resType != valType)
1545     return op.emitOpError(
1546         "expected LLVM IR result type to match type for operand #1");
1547   if (op.bin_op() == AtomicBinOp::fadd || op.bin_op() == AtomicBinOp::fsub) {
1548     if (!valType.isFloatingPointTy())
1549       return op.emitOpError("expected LLVM IR floating point type");
1550   } else if (op.bin_op() == AtomicBinOp::xchg) {
1551     if (!valType.isIntegerTy(8) && !valType.isIntegerTy(16) &&
1552         !valType.isIntegerTy(32) && !valType.isIntegerTy(64) &&
1553         !valType.isBFloatTy() && !valType.isHalfTy() && !valType.isFloatTy() &&
1554         !valType.isDoubleTy())
1555       return op.emitOpError("unexpected LLVM IR type for 'xchg' bin_op");
1556   } else {
1557     if (!valType.isIntegerTy(8) && !valType.isIntegerTy(16) &&
1558         !valType.isIntegerTy(32) && !valType.isIntegerTy(64))
1559       return op.emitOpError("expected LLVM IR integer type");
1560   }
1561   return success();
1562 }
1563 
1564 //===----------------------------------------------------------------------===//
1565 // Printer, parser and verifier for LLVM::AtomicCmpXchgOp.
1566 //===----------------------------------------------------------------------===//
1567 
1568 static void printAtomicCmpXchgOp(OpAsmPrinter &p, AtomicCmpXchgOp &op) {
1569   p << op.getOperationName() << ' ' << op.ptr() << ", " << op.cmp() << ", "
1570     << op.val() << ' ' << stringifyAtomicOrdering(op.success_ordering()) << ' '
1571     << stringifyAtomicOrdering(op.failure_ordering());
1572   p.printOptionalAttrDict(op.getAttrs(),
1573                           {"success_ordering", "failure_ordering"});
1574   p << " : " << op.val().getType();
1575 }
1576 
1577 // <operation> ::= `llvm.cmpxchg` ssa-use `,` ssa-use `,` ssa-use
1578 //                 keyword keyword attribute-dict? `:` type
1579 static ParseResult parseAtomicCmpXchgOp(OpAsmParser &parser,
1580                                         OperationState &result) {
1581   auto &builder = parser.getBuilder();
1582   LLVMType type;
1583   OpAsmParser::OperandType ptr, cmp, val;
1584   if (parser.parseOperand(ptr) || parser.parseComma() ||
1585       parser.parseOperand(cmp) || parser.parseComma() ||
1586       parser.parseOperand(val) ||
1587       parseAtomicOrdering(parser, result, "success_ordering") ||
1588       parseAtomicOrdering(parser, result, "failure_ordering") ||
1589       parser.parseOptionalAttrDict(result.attributes) ||
1590       parser.parseColonType(type) ||
1591       parser.resolveOperand(ptr, type.getPointerTo(), result.operands) ||
1592       parser.resolveOperand(cmp, type, result.operands) ||
1593       parser.resolveOperand(val, type, result.operands))
1594     return failure();
1595 
1596   auto boolType = LLVMType::getInt1Ty(builder.getContext());
1597   auto resultType = LLVMType::getStructTy(type, boolType);
1598   result.addTypes(resultType);
1599 
1600   return success();
1601 }
1602 
1603 static LogicalResult verify(AtomicCmpXchgOp op) {
1604   auto ptrType = op.ptr().getType().cast<LLVM::LLVMType>();
1605   if (!ptrType.isPointerTy())
1606     return op.emitOpError("expected LLVM IR pointer type for operand #0");
1607   auto cmpType = op.cmp().getType().cast<LLVM::LLVMType>();
1608   auto valType = op.val().getType().cast<LLVM::LLVMType>();
1609   if (cmpType != ptrType.getPointerElementTy() || cmpType != valType)
1610     return op.emitOpError("expected LLVM IR element type for operand #0 to "
1611                           "match type for all other operands");
1612   if (!valType.isPointerTy() && !valType.isIntegerTy(8) &&
1613       !valType.isIntegerTy(16) && !valType.isIntegerTy(32) &&
1614       !valType.isIntegerTy(64) && !valType.isBFloatTy() &&
1615       !valType.isHalfTy() && !valType.isFloatTy() && !valType.isDoubleTy())
1616     return op.emitOpError("unexpected LLVM IR type");
1617   if (op.success_ordering() < AtomicOrdering::monotonic ||
1618       op.failure_ordering() < AtomicOrdering::monotonic)
1619     return op.emitOpError("ordering must be at least 'monotonic'");
1620   if (op.failure_ordering() == AtomicOrdering::release ||
1621       op.failure_ordering() == AtomicOrdering::acq_rel)
1622     return op.emitOpError("failure ordering cannot be 'release' or 'acq_rel'");
1623   return success();
1624 }
1625 
1626 //===----------------------------------------------------------------------===//
1627 // Printer, parser and verifier for LLVM::FenceOp.
1628 //===----------------------------------------------------------------------===//
1629 
1630 // <operation> ::= `llvm.fence` (`syncscope(`strAttr`)`)? keyword
1631 // attribute-dict?
1632 static ParseResult parseFenceOp(OpAsmParser &parser, OperationState &result) {
1633   StringAttr sScope;
1634   StringRef syncscopeKeyword = "syncscope";
1635   if (!failed(parser.parseOptionalKeyword(syncscopeKeyword))) {
1636     if (parser.parseLParen() ||
1637         parser.parseAttribute(sScope, syncscopeKeyword, result.attributes) ||
1638         parser.parseRParen())
1639       return failure();
1640   } else {
1641     result.addAttribute(syncscopeKeyword,
1642                         parser.getBuilder().getStringAttr(""));
1643   }
1644   if (parseAtomicOrdering(parser, result, "ordering") ||
1645       parser.parseOptionalAttrDict(result.attributes))
1646     return failure();
1647   return success();
1648 }
1649 
1650 static void printFenceOp(OpAsmPrinter &p, FenceOp &op) {
1651   StringRef syncscopeKeyword = "syncscope";
1652   p << op.getOperationName() << ' ';
1653   if (!op.getAttr(syncscopeKeyword).cast<StringAttr>().getValue().empty())
1654     p << "syncscope(" << op.getAttr(syncscopeKeyword) << ") ";
1655   p << stringifyAtomicOrdering(op.ordering());
1656 }
1657 
1658 static LogicalResult verify(FenceOp &op) {
1659   if (op.ordering() == AtomicOrdering::not_atomic ||
1660       op.ordering() == AtomicOrdering::unordered ||
1661       op.ordering() == AtomicOrdering::monotonic)
1662     return op.emitOpError("can be given only acquire, release, acq_rel, "
1663                           "and seq_cst orderings");
1664   return success();
1665 }
1666 
1667 //===----------------------------------------------------------------------===//
1668 // LLVMDialect initialization, type parsing, and registration.
1669 //===----------------------------------------------------------------------===//
1670 
1671 namespace mlir {
1672 namespace LLVM {
1673 namespace detail {
1674 struct LLVMDialectImpl {
1675   LLVMDialectImpl() : layout("") {}
1676 
1677   /// Default data layout to use.
1678   // TODO: this should be moved to some Op equivalent to LLVM module and
1679   // eventually replaced with a proper MLIR data layout.
1680   llvm::DataLayout layout;
1681 };
1682 } // end namespace detail
1683 } // end namespace LLVM
1684 } // end namespace mlir
1685 
1686 void LLVMDialect::initialize() {
1687   impl = new detail::LLVMDialectImpl();
1688   // clang-format off
1689   addTypes<LLVMVoidType,
1690            LLVMHalfType,
1691            LLVMBFloatType,
1692            LLVMFloatType,
1693            LLVMDoubleType,
1694            LLVMFP128Type,
1695            LLVMX86FP80Type,
1696            LLVMPPCFP128Type,
1697            LLVMX86MMXType,
1698            LLVMTokenType,
1699            LLVMLabelType,
1700            LLVMMetadataType,
1701            LLVMFunctionType,
1702            LLVMIntegerType,
1703            LLVMPointerType,
1704            LLVMFixedVectorType,
1705            LLVMScalableVectorType,
1706            LLVMArrayType,
1707            LLVMStructType>();
1708   // clang-format on
1709   addOperations<
1710 #define GET_OP_LIST
1711 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
1712       >();
1713 
1714   // Support unknown operations because not all LLVM operations are registered.
1715   allowUnknownOperations();
1716 }
1717 
1718 LLVMDialect::~LLVMDialect() { delete impl; }
1719 
1720 #define GET_OP_CLASSES
1721 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
1722 
1723 const llvm::DataLayout &LLVMDialect::getDataLayout() { return impl->layout; }
1724 
1725 /// Parse a type registered to this dialect.
1726 Type LLVMDialect::parseType(DialectAsmParser &parser) const {
1727   return detail::parseType(parser);
1728 }
1729 
1730 /// Print a type registered to this dialect.
1731 void LLVMDialect::printType(Type type, DialectAsmPrinter &os) const {
1732   return detail::printType(type.cast<LLVMType>(), os);
1733 }
1734 
1735 /// Verify LLVMIR function argument attributes.
1736 LogicalResult LLVMDialect::verifyRegionArgAttribute(Operation *op,
1737                                                     unsigned regionIdx,
1738                                                     unsigned argIdx,
1739                                                     NamedAttribute argAttr) {
1740   // Check that llvm.noalias is a boolean attribute.
1741   if (argAttr.first == "llvm.noalias" && !argAttr.second.isa<BoolAttr>())
1742     return op->emitError()
1743            << "llvm.noalias argument attribute of non boolean type";
1744   // Check that llvm.align is an integer attribute.
1745   if (argAttr.first == "llvm.align" && !argAttr.second.isa<IntegerAttr>())
1746     return op->emitError()
1747            << "llvm.align argument attribute of non integer type";
1748   return success();
1749 }
1750 
1751 //===----------------------------------------------------------------------===//
1752 // Utility functions.
1753 //===----------------------------------------------------------------------===//
1754 
1755 Value mlir::LLVM::createGlobalString(Location loc, OpBuilder &builder,
1756                                      StringRef name, StringRef value,
1757                                      LLVM::Linkage linkage) {
1758   assert(builder.getInsertionBlock() &&
1759          builder.getInsertionBlock()->getParentOp() &&
1760          "expected builder to point to a block constrained in an op");
1761   auto module =
1762       builder.getInsertionBlock()->getParentOp()->getParentOfType<ModuleOp>();
1763   assert(module && "builder points to an op outside of a module");
1764 
1765   // Create the global at the entry of the module.
1766   OpBuilder moduleBuilder(module.getBodyRegion());
1767   MLIRContext *ctx = builder.getContext();
1768   auto type =
1769       LLVM::LLVMType::getArrayTy(LLVM::LLVMType::getInt8Ty(ctx), value.size());
1770   auto global = moduleBuilder.create<LLVM::GlobalOp>(
1771       loc, type, /*isConstant=*/true, linkage, name,
1772       builder.getStringAttr(value));
1773 
1774   // Get the pointer to the first character in the global string.
1775   Value globalPtr = builder.create<LLVM::AddressOfOp>(loc, global);
1776   Value cst0 = builder.create<LLVM::ConstantOp>(
1777       loc, LLVM::LLVMType::getInt64Ty(ctx),
1778       builder.getIntegerAttr(builder.getIndexType(), 0));
1779   return builder.create<LLVM::GEPOp>(loc, LLVM::LLVMType::getInt8PtrTy(ctx),
1780                                      globalPtr, ArrayRef<Value>({cst0, cst0}));
1781 }
1782 
1783 bool mlir::LLVM::satisfiesLLVMModule(Operation *op) {
1784   return op->hasTrait<OpTrait::SymbolTable>() &&
1785          op->hasTrait<OpTrait::IsIsolatedFromAbove>();
1786 }
1787