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