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