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