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