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