MLIR  22.0.0git
ModuleImport.cpp
Go to the documentation of this file.
1 //===- ModuleImport.cpp - LLVM to MLIR conversion ---------------*- C++ -*-===//
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 implements the import of an LLVM IR module into an LLVM dialect
10 // module.
11 //
12 //===----------------------------------------------------------------------===//
13 
17 
18 #include "AttrKindDetail.h"
19 #include "DebugImporter.h"
20 #include "LoopAnnotationImporter.h"
21 
22 #include "mlir/Dialect/DLTI/DLTI.h"
24 #include "mlir/IR/Builders.h"
25 #include "mlir/IR/Matchers.h"
29 
30 #include "llvm/ADT/DepthFirstIterator.h"
31 #include "llvm/ADT/PostOrderIterator.h"
32 #include "llvm/ADT/ScopeExit.h"
33 #include "llvm/ADT/StringExtras.h"
34 #include "llvm/ADT/TypeSwitch.h"
35 #include "llvm/IR/Comdat.h"
36 #include "llvm/IR/Constants.h"
37 #include "llvm/IR/InlineAsm.h"
38 #include "llvm/IR/InstIterator.h"
39 #include "llvm/IR/Instructions.h"
40 #include "llvm/IR/IntrinsicInst.h"
41 #include "llvm/IR/Metadata.h"
42 #include "llvm/IR/Operator.h"
43 #include "llvm/Support/ModRef.h"
44 #include <optional>
45 
46 using namespace mlir;
47 using namespace mlir::LLVM;
48 using namespace mlir::LLVM::detail;
49 
50 #include "mlir/Dialect/LLVMIR/LLVMConversionEnumsFromLLVM.inc"
51 
52 // Utility to print an LLVM value as a string for passing to emitError().
53 // FIXME: Diagnostic should be able to natively handle types that have
54 // operator << (raw_ostream&) defined.
55 static std::string diag(const llvm::Value &value) {
56  std::string str;
57  llvm::raw_string_ostream os(str);
58  os << value;
59  return str;
60 }
61 
62 // Utility to print an LLVM metadata node as a string for passing
63 // to emitError(). The module argument is needed to print the nodes
64 // canonically numbered.
65 static std::string diagMD(const llvm::Metadata *node,
66  const llvm::Module *module) {
67  std::string str;
68  llvm::raw_string_ostream os(str);
69  node->print(os, module, /*IsForDebug=*/true);
70  return str;
71 }
72 
73 /// Returns the name of the global_ctors global variables.
74 static constexpr StringRef getGlobalCtorsVarName() {
75  return "llvm.global_ctors";
76 }
77 
78 /// Prefix used for symbols of nameless llvm globals.
79 static constexpr StringRef getNamelessGlobalPrefix() {
80  return "mlir.llvm.nameless_global";
81 }
82 
83 /// Returns the name of the global_dtors global variables.
84 static constexpr StringRef getGlobalDtorsVarName() {
85  return "llvm.global_dtors";
86 }
87 
88 /// Returns the symbol name for the module-level comdat operation. It must not
89 /// conflict with the user namespace.
90 static constexpr StringRef getGlobalComdatOpName() {
91  return "__llvm_global_comdat";
92 }
93 
94 /// Converts the sync scope identifier of `inst` to the string representation
95 /// necessary to build an atomic LLVM dialect operation. Returns the empty
96 /// string if the operation has either no sync scope or the default system-level
97 /// sync scope attached. The atomic operations only set their sync scope
98 /// attribute if they have a non-default sync scope attached.
99 static StringRef getLLVMSyncScope(llvm::Instruction *inst) {
100  std::optional<llvm::SyncScope::ID> syncScopeID =
101  llvm::getAtomicSyncScopeID(inst);
102  if (!syncScopeID)
103  return "";
104 
105  // Search the sync scope name for the given identifier. The default
106  // system-level sync scope thereby maps to the empty string.
107  SmallVector<StringRef> syncScopeName;
108  llvm::LLVMContext &llvmContext = inst->getContext();
109  llvmContext.getSyncScopeNames(syncScopeName);
110  auto *it = llvm::find_if(syncScopeName, [&](StringRef name) {
111  return *syncScopeID == llvmContext.getOrInsertSyncScopeID(name);
112  });
113  if (it != syncScopeName.end())
114  return *it;
115  llvm_unreachable("incorrect sync scope identifier");
116 }
117 
118 /// Converts an array of unsigned indices to a signed integer position array.
120  SmallVector<int64_t> position;
121  llvm::append_range(position, indices);
122  return position;
123 }
124 
125 /// Converts the LLVM instructions that have a generated MLIR builder. Using a
126 /// static implementation method called from the module import ensures the
127 /// builders have to use the `moduleImport` argument and cannot directly call
128 /// import methods. As a result, both the intrinsic and the instruction MLIR
129 /// builders have to use the `moduleImport` argument and none of them has direct
130 /// access to the private module import methods.
131 static LogicalResult convertInstructionImpl(OpBuilder &odsBuilder,
132  llvm::Instruction *inst,
133  ModuleImport &moduleImport,
134  LLVMImportInterface &iface) {
135  // Copy the operands to an LLVM operands array reference for conversion.
136  SmallVector<llvm::Value *> operands(inst->operands());
137  ArrayRef<llvm::Value *> llvmOperands(operands);
138 
139  // Convert all instructions that provide an MLIR builder.
140  if (iface.isConvertibleInstruction(inst->getOpcode()))
141  return iface.convertInstruction(odsBuilder, inst, llvmOperands,
142  moduleImport);
143  // TODO: Implement the `convertInstruction` hooks in the
144  // `LLVMDialectLLVMIRImportInterface` and move the following include there.
145 #include "mlir/Dialect/LLVMIR/LLVMOpFromLLVMIRConversions.inc"
146 
147  return failure();
148 }
149 
150 /// Get a topologically sorted list of blocks for the given basic blocks.
154  for (llvm::BasicBlock *basicBlock : basicBlocks) {
155  if (!blocks.contains(basicBlock)) {
156  llvm::ReversePostOrderTraversal<llvm::BasicBlock *> traversal(basicBlock);
157  blocks.insert_range(traversal);
158  }
159  }
160  assert(blocks.size() == basicBlocks.size() && "some blocks are not sorted");
161  return blocks;
162 }
163 
164 ModuleImport::ModuleImport(ModuleOp mlirModule,
165  std::unique_ptr<llvm::Module> llvmModule,
166  bool emitExpensiveWarnings,
167  bool importEmptyDICompositeTypes,
168  bool preferUnregisteredIntrinsics,
169  bool importStructsAsLiterals)
170  : builder(mlirModule->getContext()), context(mlirModule->getContext()),
171  mlirModule(mlirModule), llvmModule(std::move(llvmModule)),
172  iface(mlirModule->getContext()),
173  typeTranslator(*mlirModule->getContext(), importStructsAsLiterals),
174  debugImporter(std::make_unique<DebugImporter>(
175  mlirModule, importEmptyDICompositeTypes)),
176  loopAnnotationImporter(
177  std::make_unique<LoopAnnotationImporter>(*this, builder)),
178  emitExpensiveWarnings(emitExpensiveWarnings),
179  preferUnregisteredIntrinsics(preferUnregisteredIntrinsics) {
180  builder.setInsertionPointToStart(mlirModule.getBody());
181 }
182 
183 ComdatOp ModuleImport::getGlobalComdatOp() {
184  if (globalComdatOp)
185  return globalComdatOp;
186 
187  OpBuilder::InsertionGuard guard(builder);
188  builder.setInsertionPointToEnd(mlirModule.getBody());
189  globalComdatOp =
190  ComdatOp::create(builder, mlirModule.getLoc(), getGlobalComdatOpName());
191  globalInsertionOp = globalComdatOp;
192  return globalComdatOp;
193 }
194 
195 LogicalResult ModuleImport::processTBAAMetadata(const llvm::MDNode *node) {
196  Location loc = mlirModule.getLoc();
197 
198  // If `node` is a valid TBAA root node, then return its optional identity
199  // string, otherwise return failure.
200  auto getIdentityIfRootNode =
201  [&](const llvm::MDNode *node) -> FailureOr<std::optional<StringRef>> {
202  // Root node, e.g.:
203  // !0 = !{!"Simple C/C++ TBAA"}
204  // !1 = !{}
205  if (node->getNumOperands() > 1)
206  return failure();
207  // If the operand is MDString, then assume that this is a root node.
208  if (node->getNumOperands() == 1)
209  if (const auto *op0 = dyn_cast<const llvm::MDString>(node->getOperand(0)))
210  return std::optional<StringRef>{op0->getString()};
211  return std::optional<StringRef>{};
212  };
213 
214  // If `node` looks like a TBAA type descriptor metadata,
215  // then return true, if it is a valid node, and false otherwise.
216  // If it does not look like a TBAA type descriptor metadata, then
217  // return std::nullopt.
218  // If `identity` and `memberTypes/Offsets` are non-null, then they will
219  // contain the converted metadata operands for a valid TBAA node (i.e. when
220  // true is returned).
221  auto isTypeDescriptorNode = [&](const llvm::MDNode *node,
222  StringRef *identity = nullptr,
224  nullptr) -> std::optional<bool> {
225  unsigned numOperands = node->getNumOperands();
226  // Type descriptor, e.g.:
227  // !1 = !{!"int", !0, /*optional*/i64 0} /* scalar int type */
228  // !2 = !{!"agg_t", !1, i64 0} /* struct agg_t { int x; } */
229  if (numOperands < 2)
230  return std::nullopt;
231 
232  // TODO: support "new" format (D41501) for type descriptors,
233  // where the first operand is an MDNode.
234  const auto *identityNode =
235  dyn_cast<const llvm::MDString>(node->getOperand(0));
236  if (!identityNode)
237  return std::nullopt;
238 
239  // This should be a type descriptor node.
240  if (identity)
241  *identity = identityNode->getString();
242 
243  for (unsigned pairNum = 0, e = numOperands / 2; pairNum < e; ++pairNum) {
244  const auto *memberNode =
245  dyn_cast<const llvm::MDNode>(node->getOperand(2 * pairNum + 1));
246  if (!memberNode) {
247  emitError(loc) << "operand '" << 2 * pairNum + 1 << "' must be MDNode: "
248  << diagMD(node, llvmModule.get());
249  return false;
250  }
251  int64_t offset = 0;
252  if (2 * pairNum + 2 >= numOperands) {
253  // Allow for optional 0 offset in 2-operand nodes.
254  if (numOperands != 2) {
255  emitError(loc) << "missing member offset: "
256  << diagMD(node, llvmModule.get());
257  return false;
258  }
259  } else {
260  auto *offsetCI = llvm::mdconst::dyn_extract<llvm::ConstantInt>(
261  node->getOperand(2 * pairNum + 2));
262  if (!offsetCI) {
263  emitError(loc) << "operand '" << 2 * pairNum + 2
264  << "' must be ConstantInt: "
265  << diagMD(node, llvmModule.get());
266  return false;
267  }
268  offset = offsetCI->getZExtValue();
269  }
270 
271  if (members)
272  members->push_back(TBAAMemberAttr::get(
273  cast<TBAANodeAttr>(tbaaMapping.lookup(memberNode)), offset));
274  }
275 
276  return true;
277  };
278 
279  // If `node` looks like a TBAA access tag metadata,
280  // then return true, if it is a valid node, and false otherwise.
281  // If it does not look like a TBAA access tag metadata, then
282  // return std::nullopt.
283  // If the other arguments are non-null, then they will contain
284  // the converted metadata operands for a valid TBAA node (i.e. when true is
285  // returned).
286  auto isTagNode = [&](const llvm::MDNode *node,
287  TBAATypeDescriptorAttr *baseAttr = nullptr,
288  TBAATypeDescriptorAttr *accessAttr = nullptr,
289  int64_t *offset = nullptr,
290  bool *isConstant = nullptr) -> std::optional<bool> {
291  // Access tag, e.g.:
292  // !3 = !{!1, !1, i64 0} /* scalar int access */
293  // !4 = !{!2, !1, i64 0} /* agg_t::x access */
294  //
295  // Optional 4th argument is ConstantInt 0/1 identifying whether
296  // the location being accessed is "constant" (see for details:
297  // https://llvm.org/docs/LangRef.html#representation).
298  unsigned numOperands = node->getNumOperands();
299  if (numOperands != 3 && numOperands != 4)
300  return std::nullopt;
301  const auto *baseMD = dyn_cast<const llvm::MDNode>(node->getOperand(0));
302  const auto *accessMD = dyn_cast<const llvm::MDNode>(node->getOperand(1));
303  auto *offsetCI =
304  llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(2));
305  if (!baseMD || !accessMD || !offsetCI)
306  return std::nullopt;
307  // TODO: support "new" TBAA format, if needed (see D41501).
308  // In the "old" format the first operand of the access type
309  // metadata is MDString. We have to distinguish the formats,
310  // because access tags have the same structure, but different
311  // meaning for the operands.
312  if (accessMD->getNumOperands() < 1 ||
313  !isa<llvm::MDString>(accessMD->getOperand(0)))
314  return std::nullopt;
315  bool isConst = false;
316  if (numOperands == 4) {
317  auto *isConstantCI =
318  llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(3));
319  if (!isConstantCI) {
320  emitError(loc) << "operand '3' must be ConstantInt: "
321  << diagMD(node, llvmModule.get());
322  return false;
323  }
324  isConst = isConstantCI->getValue()[0];
325  }
326  if (baseAttr)
327  *baseAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(baseMD));
328  if (accessAttr)
329  *accessAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(accessMD));
330  if (offset)
331  *offset = offsetCI->getZExtValue();
332  if (isConstant)
333  *isConstant = isConst;
334  return true;
335  };
336 
337  // Do a post-order walk over the TBAA Graph. Since a correct TBAA Graph is a
338  // DAG, a post-order walk guarantees that we convert any metadata node we
339  // depend on, prior to converting the current node.
342  workList.push_back(node);
343  while (!workList.empty()) {
344  const llvm::MDNode *current = workList.back();
345  if (tbaaMapping.contains(current)) {
346  // Already converted. Just pop from the worklist.
347  workList.pop_back();
348  continue;
349  }
350 
351  // If any child of this node is not yet converted, don't pop the current
352  // node from the worklist but push the not-yet-converted children in the
353  // front of the worklist.
354  bool anyChildNotConverted = false;
355  for (const llvm::MDOperand &operand : current->operands())
356  if (auto *childNode = dyn_cast_or_null<const llvm::MDNode>(operand.get()))
357  if (!tbaaMapping.contains(childNode)) {
358  workList.push_back(childNode);
359  anyChildNotConverted = true;
360  }
361 
362  if (anyChildNotConverted) {
363  // If this is the second time we failed to convert an element in the
364  // worklist it must be because a child is dependent on it being converted
365  // and we have a cycle in the graph. Cycles are not allowed in TBAA
366  // graphs.
367  if (!seen.insert(current).second)
368  return emitError(loc) << "has cycle in TBAA graph: "
369  << diagMD(current, llvmModule.get());
370 
371  continue;
372  }
373 
374  // Otherwise simply import the current node.
375  workList.pop_back();
376 
377  FailureOr<std::optional<StringRef>> rootNodeIdentity =
378  getIdentityIfRootNode(current);
379  if (succeeded(rootNodeIdentity)) {
380  StringAttr stringAttr = *rootNodeIdentity
381  ? builder.getStringAttr(**rootNodeIdentity)
382  : nullptr;
383  // The root nodes do not have operands, so we can create
384  // the TBAARootAttr on the first walk.
385  tbaaMapping.insert({current, builder.getAttr<TBAARootAttr>(stringAttr)});
386  continue;
387  }
388 
389  StringRef identity;
391  if (std::optional<bool> isValid =
392  isTypeDescriptorNode(current, &identity, &members)) {
393  assert(isValid.value() && "type descriptor node must be valid");
394 
395  tbaaMapping.insert({current, builder.getAttr<TBAATypeDescriptorAttr>(
396  identity, members)});
397  continue;
398  }
399 
400  TBAATypeDescriptorAttr baseAttr, accessAttr;
401  int64_t offset;
402  bool isConstant;
403  if (std::optional<bool> isValid =
404  isTagNode(current, &baseAttr, &accessAttr, &offset, &isConstant)) {
405  assert(isValid.value() && "access tag node must be valid");
406  tbaaMapping.insert(
407  {current, builder.getAttr<TBAATagAttr>(baseAttr, accessAttr, offset,
408  isConstant)});
409  continue;
410  }
411 
412  return emitError(loc) << "unsupported TBAA node format: "
413  << diagMD(current, llvmModule.get());
414  }
415  return success();
416 }
417 
418 LogicalResult
419 ModuleImport::processAccessGroupMetadata(const llvm::MDNode *node) {
420  Location loc = mlirModule.getLoc();
421  if (failed(loopAnnotationImporter->translateAccessGroup(node, loc)))
422  return emitError(loc) << "unsupported access group node: "
423  << diagMD(node, llvmModule.get());
424  return success();
425 }
426 
427 LogicalResult
428 ModuleImport::processAliasScopeMetadata(const llvm::MDNode *node) {
429  Location loc = mlirModule.getLoc();
430  // Helper that verifies the node has a self reference operand.
431  auto verifySelfRef = [](const llvm::MDNode *node) {
432  return node->getNumOperands() != 0 &&
433  node == dyn_cast<llvm::MDNode>(node->getOperand(0));
434  };
435  auto verifySelfRefOrString = [](const llvm::MDNode *node) {
436  return node->getNumOperands() != 0 &&
437  (node == dyn_cast<llvm::MDNode>(node->getOperand(0)) ||
438  isa<llvm::MDString>(node->getOperand(0)));
439  };
440  // Helper that verifies the given operand is a string or does not exist.
441  auto verifyDescription = [](const llvm::MDNode *node, unsigned idx) {
442  return idx >= node->getNumOperands() ||
443  isa<llvm::MDString>(node->getOperand(idx));
444  };
445 
446  auto getIdAttr = [&](const llvm::MDNode *node) -> Attribute {
447  if (verifySelfRef(node))
448  return DistinctAttr::create(builder.getUnitAttr());
449 
450  auto name = cast<llvm::MDString>(node->getOperand(0));
451  return builder.getStringAttr(name->getString());
452  };
453 
454  // Helper that creates an alias scope domain attribute.
455  auto createAliasScopeDomainOp = [&](const llvm::MDNode *aliasDomain) {
456  StringAttr description = nullptr;
457  if (aliasDomain->getNumOperands() >= 2)
458  if (auto *operand = dyn_cast<llvm::MDString>(aliasDomain->getOperand(1)))
459  description = builder.getStringAttr(operand->getString());
460  Attribute idAttr = getIdAttr(aliasDomain);
461  return builder.getAttr<AliasScopeDomainAttr>(idAttr, description);
462  };
463 
464  // Collect the alias scopes and domains to translate them.
465  for (const llvm::MDOperand &operand : node->operands()) {
466  if (const auto *scope = dyn_cast<llvm::MDNode>(operand)) {
467  llvm::AliasScopeNode aliasScope(scope);
468  const llvm::MDNode *domain = aliasScope.getDomain();
469 
470  // Verify the scope node points to valid scope metadata which includes
471  // verifying its domain. Perform the verification before looking it up in
472  // the alias scope mapping since it could have been inserted as a domain
473  // node before.
474  if (!verifySelfRefOrString(scope) || !domain ||
475  !verifyDescription(scope, 2))
476  return emitError(loc) << "unsupported alias scope node: "
477  << diagMD(scope, llvmModule.get());
478  if (!verifySelfRefOrString(domain) || !verifyDescription(domain, 1))
479  return emitError(loc) << "unsupported alias domain node: "
480  << diagMD(domain, llvmModule.get());
481 
482  if (aliasScopeMapping.contains(scope))
483  continue;
484 
485  // Convert the domain metadata node if it has not been translated before.
486  auto it = aliasScopeMapping.find(aliasScope.getDomain());
487  if (it == aliasScopeMapping.end()) {
488  auto aliasScopeDomainOp = createAliasScopeDomainOp(domain);
489  it = aliasScopeMapping.try_emplace(domain, aliasScopeDomainOp).first;
490  }
491 
492  // Convert the scope metadata node if it has not been converted before.
493  StringAttr description = nullptr;
494  if (!aliasScope.getName().empty())
495  description = builder.getStringAttr(aliasScope.getName());
496  Attribute idAttr = getIdAttr(scope);
497  auto aliasScopeOp = builder.getAttr<AliasScopeAttr>(
498  idAttr, cast<AliasScopeDomainAttr>(it->second), description);
499 
500  aliasScopeMapping.try_emplace(aliasScope.getNode(), aliasScopeOp);
501  }
502  }
503  return success();
504 }
505 
506 FailureOr<SmallVector<AliasScopeAttr>>
507 ModuleImport::lookupAliasScopeAttrs(const llvm::MDNode *node) const {
508  SmallVector<AliasScopeAttr> aliasScopes;
509  aliasScopes.reserve(node->getNumOperands());
510  for (const llvm::MDOperand &operand : node->operands()) {
511  auto *node = cast<llvm::MDNode>(operand.get());
512  aliasScopes.push_back(
513  dyn_cast_or_null<AliasScopeAttr>(aliasScopeMapping.lookup(node)));
514  }
515  // Return failure if one of the alias scope lookups failed.
516  if (llvm::is_contained(aliasScopes, nullptr))
517  return failure();
518  return aliasScopes;
519 }
520 
521 void ModuleImport::addDebugIntrinsic(llvm::CallInst *intrinsic) {
522  debugIntrinsics.insert(intrinsic);
523 }
524 
525 static Attribute convertCGProfileModuleFlagValue(ModuleOp mlirModule,
526  llvm::MDTuple *mdTuple) {
527  auto getLLVMFunction =
528  [&](const llvm::MDOperand &funcMDO) -> llvm::Function * {
529  auto *f = cast_or_null<llvm::ValueAsMetadata>(funcMDO);
530  // nullptr is a valid value for the function pointer.
531  if (!f)
532  return nullptr;
533  auto *llvmFn = cast<llvm::Function>(f->getValue()->stripPointerCasts());
534  return llvmFn;
535  };
536 
537  // Each tuple element becomes one ModuleFlagCGProfileEntryAttr.
538  SmallVector<Attribute> cgProfile;
539  for (unsigned i = 0; i < mdTuple->getNumOperands(); i++) {
540  const llvm::MDOperand &mdo = mdTuple->getOperand(i);
541  auto *cgEntry = cast<llvm::MDNode>(mdo);
542  llvm::Constant *llvmConstant =
543  cast<llvm::ConstantAsMetadata>(cgEntry->getOperand(2))->getValue();
544  uint64_t count = cast<llvm::ConstantInt>(llvmConstant)->getZExtValue();
545  auto *fromFn = getLLVMFunction(cgEntry->getOperand(0));
546  auto *toFn = getLLVMFunction(cgEntry->getOperand(1));
547  // FlatSymbolRefAttr::get(mlirModule->getContext(), llvmFn->getName());
548  cgProfile.push_back(ModuleFlagCGProfileEntryAttr::get(
549  mlirModule->getContext(),
550  fromFn ? FlatSymbolRefAttr::get(mlirModule->getContext(),
551  fromFn->getName())
552  : nullptr,
553  toFn ? FlatSymbolRefAttr::get(mlirModule->getContext(), toFn->getName())
554  : nullptr,
555  count));
556  }
557  return ArrayAttr::get(mlirModule->getContext(), cgProfile);
558 }
559 
560 /// Extract a two element `MDTuple` from a `MDOperand`. Emit a warning in case
561 /// something else is found.
562 static llvm::MDTuple *getTwoElementMDTuple(ModuleOp mlirModule,
563  const llvm::Module *llvmModule,
564  const llvm::MDOperand &md) {
565  auto *tupleEntry = dyn_cast_or_null<llvm::MDTuple>(md);
566  if (!tupleEntry || tupleEntry->getNumOperands() != 2)
567  emitWarning(mlirModule.getLoc())
568  << "expected 2-element tuple metadata: " << diagMD(md, llvmModule);
569  return tupleEntry;
570 }
571 
572 /// Extract a constant metadata value from a two element tuple (<key, value>).
573 /// Return nullptr if requirements are not met. A warning is emitted if the
574 /// `matchKey` is different from the tuple's key.
575 static llvm::ConstantAsMetadata *getConstantMDFromKeyValueTuple(
576  ModuleOp mlirModule, const llvm::Module *llvmModule,
577  const llvm::MDOperand &md, StringRef matchKey, bool optional = false) {
578  llvm::MDTuple *tupleEntry = getTwoElementMDTuple(mlirModule, llvmModule, md);
579  if (!tupleEntry)
580  return nullptr;
581  auto *keyMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(0));
582  if (!keyMD || keyMD->getString() != matchKey) {
583  if (!optional)
584  emitWarning(mlirModule.getLoc())
585  << "expected '" << matchKey << "' key, but found: "
586  << diagMD(tupleEntry->getOperand(0), llvmModule);
587  return nullptr;
588  }
589 
590  return dyn_cast<llvm::ConstantAsMetadata>(tupleEntry->getOperand(1));
591 }
592 
593 /// Extract an integer value from a two element tuple (<key, value>).
594 /// Fail if requirements are not met. A warning is emitted if the
595 /// found value isn't a LLVM constant integer.
596 static FailureOr<uint64_t>
597 convertInt64FromKeyValueTuple(ModuleOp mlirModule,
598  const llvm::Module *llvmModule,
599  const llvm::MDOperand &md, StringRef matchKey) {
600  llvm::ConstantAsMetadata *valMD =
601  getConstantMDFromKeyValueTuple(mlirModule, llvmModule, md, matchKey);
602  if (!valMD)
603  return failure();
604 
605  if (auto *cstInt = dyn_cast<llvm::ConstantInt>(valMD->getValue()))
606  return cstInt->getZExtValue();
607 
608  emitWarning(mlirModule.getLoc())
609  << "expected integer metadata value for key '" << matchKey
610  << "': " << diagMD(md, llvmModule);
611  return failure();
612 }
613 
614 static std::optional<ProfileSummaryFormatKind>
615 convertProfileSummaryFormat(ModuleOp mlirModule, const llvm::Module *llvmModule,
616  const llvm::MDOperand &formatMD) {
617  auto *tupleEntry = getTwoElementMDTuple(mlirModule, llvmModule, formatMD);
618  if (!tupleEntry)
619  return std::nullopt;
620 
621  llvm::MDString *keyMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(0));
622  if (!keyMD || keyMD->getString() != "ProfileFormat") {
623  emitWarning(mlirModule.getLoc())
624  << "expected 'ProfileFormat' key: "
625  << diagMD(tupleEntry->getOperand(0), llvmModule);
626  return std::nullopt;
627  }
628 
629  llvm::MDString *valMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(1));
630  std::optional<ProfileSummaryFormatKind> fmtKind =
631  symbolizeProfileSummaryFormatKind(valMD->getString());
632  if (!fmtKind) {
633  emitWarning(mlirModule.getLoc())
634  << "expected 'SampleProfile', 'InstrProf' or 'CSInstrProf' values, "
635  "but found: "
636  << diagMD(valMD, llvmModule);
637  return std::nullopt;
638  }
639 
640  return fmtKind;
641 }
642 
643 static FailureOr<SmallVector<ModuleFlagProfileSummaryDetailedAttr>>
644 convertProfileSummaryDetailed(ModuleOp mlirModule,
645  const llvm::Module *llvmModule,
646  const llvm::MDOperand &summaryMD) {
647  auto *tupleEntry = getTwoElementMDTuple(mlirModule, llvmModule, summaryMD);
648  if (!tupleEntry)
649  return failure();
650 
651  llvm::MDString *keyMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(0));
652  if (!keyMD || keyMD->getString() != "DetailedSummary") {
653  emitWarning(mlirModule.getLoc())
654  << "expected 'DetailedSummary' key: "
655  << diagMD(tupleEntry->getOperand(0), llvmModule);
656  return failure();
657  }
658 
659  llvm::MDTuple *entriesMD = dyn_cast<llvm::MDTuple>(tupleEntry->getOperand(1));
660  if (!entriesMD) {
661  emitWarning(mlirModule.getLoc())
662  << "expected tuple value for 'DetailedSummary' key: "
663  << diagMD(tupleEntry->getOperand(1), llvmModule);
664  return failure();
665  }
666 
668  for (auto &&entry : entriesMD->operands()) {
669  llvm::MDTuple *entryMD = dyn_cast<llvm::MDTuple>(entry);
670  if (!entryMD || entryMD->getNumOperands() != 3) {
671  emitWarning(mlirModule.getLoc())
672  << "'DetailedSummary' entry expects 3 operands: "
673  << diagMD(entry, llvmModule);
674  return failure();
675  }
676 
677  auto *op0 = dyn_cast<llvm::ConstantAsMetadata>(entryMD->getOperand(0));
678  auto *op1 = dyn_cast<llvm::ConstantAsMetadata>(entryMD->getOperand(1));
679  auto *op2 = dyn_cast<llvm::ConstantAsMetadata>(entryMD->getOperand(2));
680  if (!op0 || !op1 || !op2) {
681  emitWarning(mlirModule.getLoc())
682  << "expected only integer entries in 'DetailedSummary': "
683  << diagMD(entry, llvmModule);
684  return failure();
685  }
686 
687  auto detaildSummaryEntry = ModuleFlagProfileSummaryDetailedAttr::get(
688  mlirModule->getContext(),
689  cast<llvm::ConstantInt>(op0->getValue())->getZExtValue(),
690  cast<llvm::ConstantInt>(op1->getValue())->getZExtValue(),
691  cast<llvm::ConstantInt>(op2->getValue())->getZExtValue());
692  detailedSummary.push_back(detaildSummaryEntry);
693  }
694  return detailedSummary;
695 }
696 
697 static Attribute
699  const llvm::Module *llvmModule,
700  llvm::MDTuple *mdTuple) {
701  unsigned profileNumEntries = mdTuple->getNumOperands();
702  if (profileNumEntries < 8) {
703  emitWarning(mlirModule.getLoc())
704  << "expected at 8 entries in 'ProfileSummary': "
705  << diagMD(mdTuple, llvmModule);
706  return nullptr;
707  }
708 
709  unsigned summayIdx = 0;
710  auto checkOptionalPosition = [&](const llvm::MDOperand &md,
711  StringRef matchKey) -> LogicalResult {
712  // Make sure we won't step over the bound of the array of summary entries.
713  // Since (non-optional) DetailedSummary always comes last, the next entry in
714  // the tuple operand array must exist.
715  if (summayIdx + 1 >= profileNumEntries) {
716  emitWarning(mlirModule.getLoc())
717  << "the last summary entry is '" << matchKey
718  << "', expected 'DetailedSummary': " << diagMD(md, llvmModule);
719  return failure();
720  }
721 
722  return success();
723  };
724 
725  auto getOptIntValue =
726  [&](const llvm::MDOperand &md,
727  StringRef matchKey) -> FailureOr<std::optional<uint64_t>> {
728  if (!getConstantMDFromKeyValueTuple(mlirModule, llvmModule, md, matchKey,
729  /*optional=*/true))
730  return FailureOr<std::optional<uint64_t>>(std::nullopt);
731  if (checkOptionalPosition(md, matchKey).failed())
732  return failure();
733  FailureOr<uint64_t> val =
734  convertInt64FromKeyValueTuple(mlirModule, llvmModule, md, matchKey);
735  if (failed(val))
736  return failure();
737  return val;
738  };
739 
740  auto getOptDoubleValue = [&](const llvm::MDOperand &md,
741  StringRef matchKey) -> FailureOr<FloatAttr> {
742  auto *valMD = getConstantMDFromKeyValueTuple(mlirModule, llvmModule, md,
743  matchKey, /*optional=*/true);
744  if (!valMD)
745  return FloatAttr{};
746  if (auto *cstFP = dyn_cast<llvm::ConstantFP>(valMD->getValue())) {
747  if (checkOptionalPosition(md, matchKey).failed())
748  return failure();
749  return FloatAttr::get(Float64Type::get(mlirModule.getContext()),
750  cstFP->getValueAPF());
751  }
752  emitWarning(mlirModule.getLoc())
753  << "expected double metadata value for key '" << matchKey
754  << "': " << diagMD(md, llvmModule);
755  return failure();
756  };
757 
758  // Build ModuleFlagProfileSummaryAttr by sequentially fetching elements in
759  // a fixed order: format, total count, etc.
760  std::optional<ProfileSummaryFormatKind> format = convertProfileSummaryFormat(
761  mlirModule, llvmModule, mdTuple->getOperand(summayIdx++));
762  if (!format.has_value())
763  return nullptr;
764 
765  FailureOr<uint64_t> totalCount = convertInt64FromKeyValueTuple(
766  mlirModule, llvmModule, mdTuple->getOperand(summayIdx++), "TotalCount");
767  if (failed(totalCount))
768  return nullptr;
769 
770  FailureOr<uint64_t> maxCount = convertInt64FromKeyValueTuple(
771  mlirModule, llvmModule, mdTuple->getOperand(summayIdx++), "MaxCount");
772  if (failed(maxCount))
773  return nullptr;
774 
775  FailureOr<uint64_t> maxInternalCount = convertInt64FromKeyValueTuple(
776  mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
777  "MaxInternalCount");
778  if (failed(maxInternalCount))
779  return nullptr;
780 
781  FailureOr<uint64_t> maxFunctionCount = convertInt64FromKeyValueTuple(
782  mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
783  "MaxFunctionCount");
784  if (failed(maxFunctionCount))
785  return nullptr;
786 
787  FailureOr<uint64_t> numCounts = convertInt64FromKeyValueTuple(
788  mlirModule, llvmModule, mdTuple->getOperand(summayIdx++), "NumCounts");
789  if (failed(numCounts))
790  return nullptr;
791 
792  FailureOr<uint64_t> numFunctions = convertInt64FromKeyValueTuple(
793  mlirModule, llvmModule, mdTuple->getOperand(summayIdx++), "NumFunctions");
794  if (failed(numFunctions))
795  return nullptr;
796 
797  // Handle optional keys.
798  FailureOr<std::optional<uint64_t>> isPartialProfile =
799  getOptIntValue(mdTuple->getOperand(summayIdx), "IsPartialProfile");
800  if (failed(isPartialProfile))
801  return nullptr;
802  if (isPartialProfile->has_value())
803  summayIdx++;
804 
805  FailureOr<FloatAttr> partialProfileRatio =
806  getOptDoubleValue(mdTuple->getOperand(summayIdx), "PartialProfileRatio");
807  if (failed(partialProfileRatio))
808  return nullptr;
809  if (*partialProfileRatio)
810  summayIdx++;
811 
812  // Handle detailed summary.
813  FailureOr<SmallVector<ModuleFlagProfileSummaryDetailedAttr>> detailed =
814  convertProfileSummaryDetailed(mlirModule, llvmModule,
815  mdTuple->getOperand(summayIdx));
816  if (failed(detailed))
817  return nullptr;
818 
819  // Build the final profile summary attribute.
821  mlirModule->getContext(), *format, *totalCount, *maxCount,
822  *maxInternalCount, *maxFunctionCount, *numCounts, *numFunctions,
823  *isPartialProfile, *partialProfileRatio, *detailed);
824 }
825 
826 /// Invoke specific handlers for each known module flag value, returns nullptr
827 /// if the key is unknown or unimplemented.
828 static Attribute
830  const llvm::Module *llvmModule, StringRef key,
831  llvm::MDTuple *mdTuple) {
832  if (key == LLVMDialect::getModuleFlagKeyCGProfileName())
833  return convertCGProfileModuleFlagValue(mlirModule, mdTuple);
834  if (key == LLVMDialect::getModuleFlagKeyProfileSummaryName())
835  return convertProfileSummaryModuleFlagValue(mlirModule, llvmModule,
836  mdTuple);
837  return nullptr;
838 }
839 
842  llvmModule->getModuleFlagsMetadata(llvmModuleFlags);
843 
844  SmallVector<Attribute> moduleFlags;
845  for (const auto [behavior, key, val] : llvmModuleFlags) {
846  Attribute valAttr = nullptr;
847  if (auto *constInt = llvm::mdconst::dyn_extract<llvm::ConstantInt>(val)) {
848  valAttr = builder.getI32IntegerAttr(constInt->getZExtValue());
849  } else if (auto *mdString = dyn_cast<llvm::MDString>(val)) {
850  valAttr = builder.getStringAttr(mdString->getString());
851  } else if (auto *mdTuple = dyn_cast<llvm::MDTuple>(val)) {
852  valAttr = convertModuleFlagValueFromMDTuple(mlirModule, llvmModule.get(),
853  key->getString(), mdTuple);
854  }
855 
856  if (!valAttr) {
857  emitWarning(mlirModule.getLoc())
858  << "unsupported module flag value for key '" << key->getString()
859  << "' : " << diagMD(val, llvmModule.get());
860  continue;
861  }
862 
863  moduleFlags.push_back(builder.getAttr<ModuleFlagAttr>(
864  convertModFlagBehaviorFromLLVM(behavior),
865  builder.getStringAttr(key->getString()), valAttr));
866  }
867 
868  if (!moduleFlags.empty())
869  LLVM::ModuleFlagsOp::create(builder, mlirModule.getLoc(),
870  builder.getArrayAttr(moduleFlags));
871 
872  return success();
873 }
874 
876  for (const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
877  if (named.getName() != "llvm.linker.options")
878  continue;
879  // llvm.linker.options operands are lists of strings.
880  for (const llvm::MDNode *node : named.operands()) {
882  options.reserve(node->getNumOperands());
883  for (const llvm::MDOperand &option : node->operands())
884  options.push_back(cast<llvm::MDString>(option)->getString());
885  LLVM::LinkerOptionsOp::create(builder, mlirModule.getLoc(),
886  builder.getStrArrayAttr(options));
887  }
888  }
889  return success();
890 }
891 
893  for (const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
894  if (named.getName() != "llvm.dependent-libraries")
895  continue;
896  SmallVector<StringRef> libraries;
897  for (const llvm::MDNode *node : named.operands()) {
898  if (node->getNumOperands() == 1)
899  if (auto *mdString = dyn_cast<llvm::MDString>(node->getOperand(0)))
900  libraries.push_back(mdString->getString());
901  }
902  if (!libraries.empty())
903  mlirModule->setAttr(LLVM::LLVMDialect::getDependentLibrariesAttrName(),
904  builder.getStrArrayAttr(libraries));
905  }
906  return success();
907 }
908 
910  for (const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
911  // llvm.ident should have a single operand. That operand is itself an
912  // MDNode with a single string operand.
913  if (named.getName() != LLVMDialect::getIdentAttrName())
914  continue;
915 
916  if (named.getNumOperands() == 1)
917  if (auto *md = dyn_cast<llvm::MDNode>(named.getOperand(0)))
918  if (md->getNumOperands() == 1)
919  if (auto *mdStr = dyn_cast<llvm::MDString>(md->getOperand(0)))
920  mlirModule->setAttr(LLVMDialect::getIdentAttrName(),
921  builder.getStringAttr(mdStr->getString()));
922  }
923  return success();
924 }
925 
927  for (const llvm::NamedMDNode &nmd : llvmModule->named_metadata()) {
928  // llvm.commandline should have a single operand. That operand is itself an
929  // MDNode with a single string operand.
930  if (nmd.getName() != LLVMDialect::getCommandlineAttrName())
931  continue;
932 
933  if (nmd.getNumOperands() == 1)
934  if (auto *md = dyn_cast<llvm::MDNode>(nmd.getOperand(0)))
935  if (md->getNumOperands() == 1)
936  if (auto *mdStr = dyn_cast<llvm::MDString>(md->getOperand(0)))
937  mlirModule->setAttr(LLVMDialect::getCommandlineAttrName(),
938  builder.getStringAttr(mdStr->getString()));
939  }
940  return success();
941 }
942 
944  OpBuilder::InsertionGuard guard(builder);
945  builder.setInsertionPointToEnd(mlirModule.getBody());
946  for (const llvm::Function &func : llvmModule->functions()) {
947  for (const llvm::Instruction &inst : llvm::instructions(func)) {
948  // Convert access group metadata nodes.
949  if (llvm::MDNode *node =
950  inst.getMetadata(llvm::LLVMContext::MD_access_group))
951  if (failed(processAccessGroupMetadata(node)))
952  return failure();
953 
954  // Convert alias analysis metadata nodes.
955  llvm::AAMDNodes aliasAnalysisNodes = inst.getAAMetadata();
956  if (!aliasAnalysisNodes)
957  continue;
958  if (aliasAnalysisNodes.TBAA)
959  if (failed(processTBAAMetadata(aliasAnalysisNodes.TBAA)))
960  return failure();
961  if (aliasAnalysisNodes.Scope)
962  if (failed(processAliasScopeMetadata(aliasAnalysisNodes.Scope)))
963  return failure();
964  if (aliasAnalysisNodes.NoAlias)
965  if (failed(processAliasScopeMetadata(aliasAnalysisNodes.NoAlias)))
966  return failure();
967  }
968  }
970  return failure();
972  return failure();
974  return failure();
976  return failure();
978  return failure();
979  return success();
980 }
981 
982 void ModuleImport::processComdat(const llvm::Comdat *comdat) {
983  if (comdatMapping.contains(comdat))
984  return;
985 
986  ComdatOp comdatOp = getGlobalComdatOp();
987  OpBuilder::InsertionGuard guard(builder);
988  builder.setInsertionPointToEnd(&comdatOp.getBody().back());
989  auto selectorOp = ComdatSelectorOp::create(
990  builder, mlirModule.getLoc(), comdat->getName(),
991  convertComdatFromLLVM(comdat->getSelectionKind()));
992  auto symbolRef =
994  FlatSymbolRefAttr::get(selectorOp.getSymNameAttr()));
995  comdatMapping.try_emplace(comdat, symbolRef);
996 }
997 
999  for (llvm::GlobalVariable &globalVar : llvmModule->globals())
1000  if (globalVar.hasComdat())
1001  processComdat(globalVar.getComdat());
1002  for (llvm::Function &func : llvmModule->functions())
1003  if (func.hasComdat())
1004  processComdat(func.getComdat());
1005  return success();
1006 }
1007 
1009  for (llvm::GlobalVariable &globalVar : llvmModule->globals()) {
1010  if (globalVar.getName() == getGlobalCtorsVarName() ||
1011  globalVar.getName() == getGlobalDtorsVarName()) {
1012  if (failed(convertGlobalCtorsAndDtors(&globalVar))) {
1013  return emitError(UnknownLoc::get(context))
1014  << "unhandled global variable: " << diag(globalVar);
1015  }
1016  continue;
1017  }
1018  if (failed(convertGlobal(&globalVar))) {
1019  return emitError(UnknownLoc::get(context))
1020  << "unhandled global variable: " << diag(globalVar);
1021  }
1022  }
1023  return success();
1024 }
1025 
1027  for (llvm::GlobalAlias &alias : llvmModule->aliases()) {
1028  if (failed(convertAlias(&alias))) {
1029  return emitError(UnknownLoc::get(context))
1030  << "unhandled global alias: " << diag(alias);
1031  }
1032  }
1033  return success();
1034 }
1035 
1037  for (llvm::GlobalIFunc &ifunc : llvmModule->ifuncs()) {
1038  if (failed(convertIFunc(&ifunc))) {
1039  return emitError(UnknownLoc::get(context))
1040  << "unhandled global ifunc: " << diag(ifunc);
1041  }
1042  }
1043  return success();
1044 }
1045 
1047  Location loc = mlirModule.getLoc();
1048  DataLayoutImporter dataLayoutImporter(
1049  context, llvmModule->getDataLayout().getStringRepresentation());
1050  if (!dataLayoutImporter.getDataLayoutSpec())
1051  return emitError(loc, "cannot translate data layout: ")
1052  << dataLayoutImporter.getLastToken();
1053 
1054  for (StringRef token : dataLayoutImporter.getUnhandledTokens())
1055  emitWarning(loc, "unhandled data layout token: ") << token;
1056 
1057  mlirModule->setAttr(DLTIDialect::kDataLayoutAttrName,
1058  dataLayoutImporter.getDataLayoutSpec());
1059  return success();
1060 }
1061 
1063  mlirModule->setAttr(
1064  LLVM::LLVMDialect::getTargetTripleAttrName(),
1065  builder.getStringAttr(llvmModule->getTargetTriple().str()));
1066 }
1067 
1069  llvm::StringRef asmStr = llvmModule->getModuleInlineAsm();
1071 
1072  for (llvm::StringRef line : llvm::split(asmStr, '\n'))
1073  if (!line.empty())
1074  asmArrayAttr.push_back(builder.getStringAttr(line));
1075 
1076  mlirModule->setAttr(LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
1077  builder.getArrayAttr(asmArrayAttr));
1078 }
1079 
1081  for (llvm::Function &func : llvmModule->functions())
1082  if (failed(processFunction(&func)))
1083  return failure();
1084  return success();
1085 }
1086 
1087 void ModuleImport::setNonDebugMetadataAttrs(llvm::Instruction *inst,
1088  Operation *op) {
1090  inst->getAllMetadataOtherThanDebugLoc(allMetadata);
1091  for (auto &[kind, node] : allMetadata) {
1092  if (!iface.isConvertibleMetadata(kind))
1093  continue;
1094  if (failed(iface.setMetadataAttrs(builder, kind, node, op, *this))) {
1095  if (emitExpensiveWarnings) {
1096  Location loc = debugImporter->translateLoc(inst->getDebugLoc());
1097  emitWarning(loc) << "unhandled metadata: "
1098  << diagMD(node, llvmModule.get()) << " on "
1099  << diag(*inst);
1100  }
1101  }
1102  }
1103 }
1104 
1105 void ModuleImport::setIntegerOverflowFlags(llvm::Instruction *inst,
1106  Operation *op) const {
1107  auto iface = cast<IntegerOverflowFlagsInterface>(op);
1108 
1109  IntegerOverflowFlags value = {};
1110  value = bitEnumSet(value, IntegerOverflowFlags::nsw, inst->hasNoSignedWrap());
1111  value =
1112  bitEnumSet(value, IntegerOverflowFlags::nuw, inst->hasNoUnsignedWrap());
1113 
1114  iface.setOverflowFlags(value);
1115 }
1116 
1117 void ModuleImport::setExactFlag(llvm::Instruction *inst, Operation *op) const {
1118  auto iface = cast<ExactFlagInterface>(op);
1119 
1120  iface.setIsExact(inst->isExact());
1121 }
1122 
1123 void ModuleImport::setDisjointFlag(llvm::Instruction *inst,
1124  Operation *op) const {
1125  auto iface = cast<DisjointFlagInterface>(op);
1126  auto instDisjoint = cast<llvm::PossiblyDisjointInst>(inst);
1127 
1128  iface.setIsDisjoint(instDisjoint->isDisjoint());
1129 }
1130 
1131 void ModuleImport::setNonNegFlag(llvm::Instruction *inst, Operation *op) const {
1132  auto iface = cast<NonNegFlagInterface>(op);
1133 
1134  iface.setNonNeg(inst->hasNonNeg());
1135 }
1136 
1137 void ModuleImport::setFastmathFlagsAttr(llvm::Instruction *inst,
1138  Operation *op) const {
1139  auto iface = cast<FastmathFlagsInterface>(op);
1140 
1141  // Even if the imported operation implements the fastmath interface, the
1142  // original instruction may not have fastmath flags set. Exit if an
1143  // instruction, such as a non floating-point function call, does not have
1144  // fastmath flags.
1145  if (!isa<llvm::FPMathOperator>(inst))
1146  return;
1147  llvm::FastMathFlags flags = inst->getFastMathFlags();
1148 
1149  // Set the fastmath bits flag-by-flag.
1150  FastmathFlags value = {};
1151  value = bitEnumSet(value, FastmathFlags::nnan, flags.noNaNs());
1152  value = bitEnumSet(value, FastmathFlags::ninf, flags.noInfs());
1153  value = bitEnumSet(value, FastmathFlags::nsz, flags.noSignedZeros());
1154  value = bitEnumSet(value, FastmathFlags::arcp, flags.allowReciprocal());
1155  value = bitEnumSet(value, FastmathFlags::contract, flags.allowContract());
1156  value = bitEnumSet(value, FastmathFlags::afn, flags.approxFunc());
1157  value = bitEnumSet(value, FastmathFlags::reassoc, flags.allowReassoc());
1158  FastmathFlagsAttr attr = FastmathFlagsAttr::get(builder.getContext(), value);
1159  iface->setAttr(iface.getFastmathAttrName(), attr);
1160 }
1161 
1162 /// Returns `type` if it is a builtin integer or floating-point vector type that
1163 /// can be used to create an attribute or nullptr otherwise. If provided,
1164 /// `arrayShape` is added to the shape of the vector to create an attribute that
1165 /// matches an array of vectors.
1166 static Type getVectorTypeForAttr(Type type, ArrayRef<int64_t> arrayShape = {}) {
1167  if (!LLVM::isCompatibleVectorType(type))
1168  return {};
1169 
1170  llvm::ElementCount numElements = LLVM::getVectorNumElements(type);
1171  if (numElements.isScalable()) {
1173  << "scalable vectors not supported";
1174  return {};
1175  }
1176 
1177  // An LLVM dialect vector can only contain scalars.
1178  Type elementType = cast<VectorType>(type).getElementType();
1179  if (!elementType.isIntOrFloat())
1180  return {};
1181 
1182  SmallVector<int64_t> shape(arrayShape);
1183  shape.push_back(numElements.getKnownMinValue());
1184  return VectorType::get(shape, elementType);
1185 }
1186 
1187 Type ModuleImport::getBuiltinTypeForAttr(Type type) {
1188  if (!type)
1189  return {};
1190 
1191  // Return builtin integer and floating-point types as is.
1192  if (type.isIntOrFloat())
1193  return type;
1194 
1195  // Return builtin vectors of integer and floating-point types as is.
1196  if (Type vectorType = getVectorTypeForAttr(type))
1197  return vectorType;
1198 
1199  // Multi-dimensional array types are converted to tensors or vectors,
1200  // depending on the innermost type being a scalar or a vector.
1201  SmallVector<int64_t> arrayShape;
1202  while (auto arrayType = dyn_cast<LLVMArrayType>(type)) {
1203  arrayShape.push_back(arrayType.getNumElements());
1204  type = arrayType.getElementType();
1205  }
1206  if (type.isIntOrFloat())
1207  return RankedTensorType::get(arrayShape, type);
1208  return getVectorTypeForAttr(type, arrayShape);
1209 }
1210 
1211 /// Returns an integer or float attribute for the provided scalar constant
1212 /// `constScalar` or nullptr if the conversion fails.
1213 static TypedAttr getScalarConstantAsAttr(OpBuilder &builder,
1214  llvm::Constant *constScalar) {
1215  MLIRContext *context = builder.getContext();
1216 
1217  // Convert scalar intergers.
1218  if (auto *constInt = dyn_cast<llvm::ConstantInt>(constScalar)) {
1219  return builder.getIntegerAttr(
1220  IntegerType::get(context, constInt->getBitWidth()),
1221  constInt->getValue());
1222  }
1223 
1224  // Convert scalar floats.
1225  if (auto *constFloat = dyn_cast<llvm::ConstantFP>(constScalar)) {
1226  llvm::Type *type = constFloat->getType();
1227  FloatType floatType =
1228  type->isBFloatTy()
1229  ? BFloat16Type::get(context)
1230  : LLVM::detail::getFloatType(context, type->getScalarSizeInBits());
1231  if (!floatType) {
1233  << "unexpected floating-point type";
1234  return {};
1235  }
1236  return builder.getFloatAttr(floatType, constFloat->getValueAPF());
1237  }
1238  return {};
1239 }
1240 
1241 /// Returns an integer or float attribute array for the provided constant
1242 /// sequence `constSequence` or nullptr if the conversion fails.
1245  llvm::ConstantDataSequential *constSequence) {
1246  SmallVector<Attribute> elementAttrs;
1247  elementAttrs.reserve(constSequence->getNumElements());
1248  for (auto idx : llvm::seq<int64_t>(0, constSequence->getNumElements())) {
1249  llvm::Constant *constElement = constSequence->getElementAsConstant(idx);
1250  elementAttrs.push_back(getScalarConstantAsAttr(builder, constElement));
1251  }
1252  return elementAttrs;
1253 }
1254 
1255 Attribute ModuleImport::getConstantAsAttr(llvm::Constant *constant) {
1256  // Convert scalar constants.
1257  if (Attribute scalarAttr = getScalarConstantAsAttr(builder, constant))
1258  return scalarAttr;
1259 
1260  // Returns the static shape of the provided type if possible.
1261  auto getConstantShape = [&](llvm::Type *type) {
1262  return llvm::dyn_cast_if_present<ShapedType>(
1263  getBuiltinTypeForAttr(convertType(type)));
1264  };
1265 
1266  // Convert one-dimensional constant arrays or vectors that store 1/2/4/8-byte
1267  // integer or half/bfloat/float/double values.
1268  if (auto *constArray = dyn_cast<llvm::ConstantDataSequential>(constant)) {
1269  if (constArray->isString())
1270  return builder.getStringAttr(constArray->getAsString());
1271  auto shape = getConstantShape(constArray->getType());
1272  if (!shape)
1273  return {};
1274  // Convert splat constants to splat elements attributes.
1275  auto *constVector = dyn_cast<llvm::ConstantDataVector>(constant);
1276  if (constVector && constVector->isSplat()) {
1277  // A vector is guaranteed to have at least size one.
1278  Attribute splatAttr = getScalarConstantAsAttr(
1279  builder, constVector->getElementAsConstant(0));
1280  return SplatElementsAttr::get(shape, splatAttr);
1281  }
1282  // Convert non-splat constants to dense elements attributes.
1283  SmallVector<Attribute> elementAttrs =
1284  getSequenceConstantAsAttrs(builder, constArray);
1285  return DenseElementsAttr::get(shape, elementAttrs);
1286  }
1287 
1288  // Convert multi-dimensional constant aggregates that store all kinds of
1289  // integer and floating-point types.
1290  if (auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(constant)) {
1291  auto shape = getConstantShape(constAggregate->getType());
1292  if (!shape)
1293  return {};
1294  // Collect the aggregate elements in depths first order.
1295  SmallVector<Attribute> elementAttrs;
1296  SmallVector<llvm::Constant *> workList = {constAggregate};
1297  while (!workList.empty()) {
1298  llvm::Constant *current = workList.pop_back_val();
1299  // Append any nested aggregates in reverse order to ensure the head
1300  // element of the nested aggregates is at the back of the work list.
1301  if (auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(current)) {
1302  for (auto idx :
1303  reverse(llvm::seq<int64_t>(0, constAggregate->getNumOperands())))
1304  workList.push_back(constAggregate->getAggregateElement(idx));
1305  continue;
1306  }
1307  // Append the elements of nested constant arrays or vectors that store
1308  // 1/2/4/8-byte integer or half/bfloat/float/double values.
1309  if (auto *constArray = dyn_cast<llvm::ConstantDataSequential>(current)) {
1310  SmallVector<Attribute> attrs =
1311  getSequenceConstantAsAttrs(builder, constArray);
1312  elementAttrs.append(attrs.begin(), attrs.end());
1313  continue;
1314  }
1315  // Append nested scalar constants that store all kinds of integer and
1316  // floating-point types.
1317  if (Attribute scalarAttr = getScalarConstantAsAttr(builder, current)) {
1318  elementAttrs.push_back(scalarAttr);
1319  continue;
1320  }
1321  // Bail if the aggregate contains a unsupported constant type such as a
1322  // constant expression.
1323  return {};
1324  }
1325  return DenseElementsAttr::get(shape, elementAttrs);
1326  }
1327 
1328  // Convert zero aggregates.
1329  if (auto *constZero = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1330  auto shape = llvm::dyn_cast_if_present<ShapedType>(
1331  getBuiltinTypeForAttr(convertType(constZero->getType())));
1332  if (!shape)
1333  return {};
1334  // Convert zero aggregates with a static shape to splat elements attributes.
1335  Attribute splatAttr = builder.getZeroAttr(shape.getElementType());
1336  assert(splatAttr && "expected non-null zero attribute for scalar types");
1337  return SplatElementsAttr::get(shape, splatAttr);
1338  }
1339  return {};
1340 }
1341 
1343 ModuleImport::getOrCreateNamelessSymbolName(llvm::GlobalVariable *globalVar) {
1344  assert(globalVar->getName().empty() &&
1345  "expected to work with a nameless global");
1346  auto [it, success] = namelessGlobals.try_emplace(globalVar);
1347  if (!success)
1348  return it->second;
1349 
1350  // Make sure the symbol name does not clash with an existing symbol.
1351  SmallString<128> globalName = SymbolTable::generateSymbolName<128>(
1353  [this](StringRef newName) { return llvmModule->getNamedValue(newName); },
1354  namelessGlobalId);
1355  auto symbolRef = FlatSymbolRefAttr::get(context, globalName);
1356  it->getSecond() = symbolRef;
1357  return symbolRef;
1358 }
1359 
1360 OpBuilder::InsertionGuard ModuleImport::setGlobalInsertionPoint() {
1361  OpBuilder::InsertionGuard guard(builder);
1362  if (globalInsertionOp)
1363  builder.setInsertionPointAfter(globalInsertionOp);
1364  else
1365  builder.setInsertionPointToStart(mlirModule.getBody());
1366  return guard;
1367 }
1368 
1369 LogicalResult ModuleImport::convertAlias(llvm::GlobalAlias *alias) {
1370  // Insert the alias after the last one or at the start of the module.
1371  OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1372 
1373  Type type = convertType(alias->getValueType());
1374  AliasOp aliasOp = AliasOp::create(builder, mlirModule.getLoc(), type,
1375  convertLinkageFromLLVM(alias->getLinkage()),
1376  alias->getName(),
1377  /*dso_local=*/alias->isDSOLocal(),
1378  /*thread_local=*/alias->isThreadLocal(),
1379  /*attrs=*/ArrayRef<NamedAttribute>());
1380  globalInsertionOp = aliasOp;
1381 
1382  clearRegionState();
1383  Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
1384  setConstantInsertionPointToStart(block);
1385  FailureOr<Value> initializer = convertConstantExpr(alias->getAliasee());
1386  if (failed(initializer))
1387  return failure();
1388  ReturnOp::create(builder, aliasOp.getLoc(), *initializer);
1389 
1390  if (alias->hasAtLeastLocalUnnamedAddr())
1391  aliasOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(alias->getUnnamedAddr()));
1392  aliasOp.setVisibility_(convertVisibilityFromLLVM(alias->getVisibility()));
1393 
1394  return success();
1395 }
1396 
1397 LogicalResult ModuleImport::convertIFunc(llvm::GlobalIFunc *ifunc) {
1398  OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1399 
1400  Type type = convertType(ifunc->getValueType());
1401  llvm::Constant *resolver = ifunc->getResolver();
1402  Type resolverType = convertType(resolver->getType());
1403  IFuncOp::create(builder, mlirModule.getLoc(), ifunc->getName(), type,
1404  resolver->getName(), resolverType,
1405  convertLinkageFromLLVM(ifunc->getLinkage()),
1406  ifunc->isDSOLocal(), ifunc->getAddressSpace(),
1407  convertUnnamedAddrFromLLVM(ifunc->getUnnamedAddr()),
1408  convertVisibilityFromLLVM(ifunc->getVisibility()));
1409  return success();
1410 }
1411 
1412 /// Converts LLVM string, integer, and enum attributes into MLIR attributes,
1413 /// skipping those in `attributesToSkip` and emitting a warning at `loc` for
1414 /// any other unsupported attributes.
1415 static ArrayAttr
1417  llvm::AttributeSet attributes,
1418  ArrayRef<StringLiteral> attributesToSkip = {}) {
1419  SmallVector<Attribute> mlirAttributes;
1420  for (llvm::Attribute attr : attributes) {
1421  StringRef attrName;
1422  if (attr.isStringAttribute())
1423  attrName = attr.getKindAsString();
1424  else
1425  attrName = llvm::Attribute::getNameFromAttrKind(attr.getKindAsEnum());
1426  if (llvm::is_contained(attributesToSkip, attrName))
1427  continue;
1428 
1429  auto keyAttr = StringAttr::get(context, attrName);
1430  if (attr.isStringAttribute()) {
1431  StringRef val = attr.getValueAsString();
1432  if (val.empty()) {
1433  // For string attributes without values, add only the attribute name.
1434  mlirAttributes.push_back(keyAttr);
1435  continue;
1436  }
1437  // For string attributes with a value, create a [name, value] pair.
1438  mlirAttributes.push_back(
1439  ArrayAttr::get(context, {keyAttr, StringAttr::get(context, val)}));
1440  continue;
1441  }
1442  if (attr.isIntAttribute()) {
1443  // For integer attributes, convert the value to a string and create a
1444  // [name, value] pair.
1445  auto val = std::to_string(attr.getValueAsInt());
1446  mlirAttributes.push_back(
1447  ArrayAttr::get(context, {keyAttr, StringAttr::get(context, val)}));
1448  continue;
1449  }
1450  if (attr.isEnumAttribute()) {
1451  // For enum attributes, add only the attribute name.
1452  mlirAttributes.push_back(keyAttr);
1453  continue;
1454  }
1455 
1456  emitWarning(loc)
1457  << "'" << attrName
1458  << "' attribute is invalid on current operation, skipping it";
1459  }
1460  return ArrayAttr::get(context, mlirAttributes);
1461 }
1462 
1463 /// Converts LLVM attributes from `globalVar` into MLIR attributes and adds them
1464 /// to `globalOp` as target-specific attributes.
1465 static void processTargetSpecificAttrs(llvm::GlobalVariable *globalVar,
1466  GlobalOp globalOp) {
1467  ArrayAttr targetSpecificAttrs = convertLLVMAttributesToMLIR(
1468  globalOp.getLoc(), globalOp.getContext(), globalVar->getAttributes());
1469  if (!targetSpecificAttrs.empty())
1470  globalOp.setTargetSpecificAttrsAttr(targetSpecificAttrs);
1471 }
1472 
1473 LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) {
1474  // Insert the global after the last one or at the start of the module.
1475  OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1476 
1477  Attribute valueAttr;
1478  if (globalVar->hasInitializer())
1479  valueAttr = getConstantAsAttr(globalVar->getInitializer());
1480  Type type = convertType(globalVar->getValueType());
1481 
1482  uint64_t alignment = 0;
1483  llvm::MaybeAlign maybeAlign = globalVar->getAlign();
1484  if (maybeAlign.has_value()) {
1485  llvm::Align align = *maybeAlign;
1486  alignment = align.value();
1487  }
1488 
1489  // Get the global expression associated with this global variable and convert
1490  // it.
1491  SmallVector<Attribute> globalExpressionAttrs;
1493  globalVar->getDebugInfo(globalExpressions);
1494 
1495  for (llvm::DIGlobalVariableExpression *expr : globalExpressions) {
1496  DIGlobalVariableExpressionAttr globalExpressionAttr =
1497  debugImporter->translateGlobalVariableExpression(expr);
1498  globalExpressionAttrs.push_back(globalExpressionAttr);
1499  }
1500 
1501  // Workaround to support LLVM's nameless globals. MLIR, in contrast to LLVM,
1502  // always requires a symbol name.
1503  StringRef globalName = globalVar->getName();
1504  if (globalName.empty())
1505  globalName = getOrCreateNamelessSymbolName(globalVar).getValue();
1506 
1507  GlobalOp globalOp = GlobalOp::create(
1508  builder, mlirModule.getLoc(), type, globalVar->isConstant(),
1509  convertLinkageFromLLVM(globalVar->getLinkage()), StringRef(globalName),
1510  valueAttr, alignment, /*addr_space=*/globalVar->getAddressSpace(),
1511  /*dso_local=*/globalVar->isDSOLocal(),
1512  /*thread_local=*/globalVar->isThreadLocal(), /*comdat=*/SymbolRefAttr(),
1513  /*attrs=*/ArrayRef<NamedAttribute>(), /*dbgExprs=*/globalExpressionAttrs);
1514  globalInsertionOp = globalOp;
1515 
1516  if (globalVar->hasInitializer() && !valueAttr) {
1517  clearRegionState();
1518  Block *block = builder.createBlock(&globalOp.getInitializerRegion());
1519  setConstantInsertionPointToStart(block);
1520  FailureOr<Value> initializer =
1521  convertConstantExpr(globalVar->getInitializer());
1522  if (failed(initializer))
1523  return failure();
1524  ReturnOp::create(builder, globalOp.getLoc(), *initializer);
1525  }
1526  if (globalVar->hasAtLeastLocalUnnamedAddr()) {
1527  globalOp.setUnnamedAddr(
1528  convertUnnamedAddrFromLLVM(globalVar->getUnnamedAddr()));
1529  }
1530  if (globalVar->hasSection())
1531  globalOp.setSection(globalVar->getSection());
1532  globalOp.setVisibility_(
1533  convertVisibilityFromLLVM(globalVar->getVisibility()));
1534 
1535  if (globalVar->hasComdat())
1536  globalOp.setComdatAttr(comdatMapping.lookup(globalVar->getComdat()));
1537 
1538  processTargetSpecificAttrs(globalVar, globalOp);
1539 
1540  return success();
1541 }
1542 
1543 LogicalResult
1544 ModuleImport::convertGlobalCtorsAndDtors(llvm::GlobalVariable *globalVar) {
1545  if (!globalVar->hasInitializer() || !globalVar->hasAppendingLinkage())
1546  return failure();
1547  llvm::Constant *initializer = globalVar->getInitializer();
1548 
1549  bool knownInit = isa<llvm::ConstantArray>(initializer) ||
1550  isa<llvm::ConstantAggregateZero>(initializer);
1551  if (!knownInit)
1552  return failure();
1553 
1554  // ConstantAggregateZero does not engage with the operand initialization
1555  // in the loop that follows - there should be no operands. This implies
1556  // empty ctor/dtor lists.
1557  if (auto *caz = dyn_cast<llvm::ConstantAggregateZero>(initializer)) {
1558  if (caz->getElementCount().getFixedValue() != 0)
1559  return failure();
1560  }
1561 
1562  SmallVector<Attribute> funcs;
1563  SmallVector<int32_t> priorities;
1564  SmallVector<Attribute> dataList;
1565  for (llvm::Value *operand : initializer->operands()) {
1566  auto *aggregate = dyn_cast<llvm::ConstantAggregate>(operand);
1567  if (!aggregate || aggregate->getNumOperands() != 3)
1568  return failure();
1569 
1570  auto *priority = dyn_cast<llvm::ConstantInt>(aggregate->getOperand(0));
1571  auto *func = dyn_cast<llvm::Function>(aggregate->getOperand(1));
1572  auto *data = dyn_cast<llvm::Constant>(aggregate->getOperand(2));
1573  if (!priority || !func || !data)
1574  return failure();
1575 
1576  auto *gv = dyn_cast_or_null<llvm::GlobalValue>(data);
1577  Attribute dataAttr;
1578  if (gv)
1579  dataAttr = FlatSymbolRefAttr::get(context, gv->getName());
1580  else if (data->isNullValue())
1581  dataAttr = ZeroAttr::get(context);
1582  else
1583  return failure();
1584 
1585  funcs.push_back(FlatSymbolRefAttr::get(context, func->getName()));
1586  priorities.push_back(priority->getValue().getZExtValue());
1587  dataList.push_back(dataAttr);
1588  }
1589 
1590  // Insert the global after the last one or at the start of the module.
1591  OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1592 
1593  if (globalVar->getName() == getGlobalCtorsVarName()) {
1594  globalInsertionOp = LLVM::GlobalCtorsOp::create(
1595  builder, mlirModule.getLoc(), builder.getArrayAttr(funcs),
1596  builder.getI32ArrayAttr(priorities), builder.getArrayAttr(dataList));
1597  return success();
1598  }
1599  globalInsertionOp = LLVM::GlobalDtorsOp::create(
1600  builder, mlirModule.getLoc(), builder.getArrayAttr(funcs),
1601  builder.getI32ArrayAttr(priorities), builder.getArrayAttr(dataList));
1602  return success();
1603 }
1604 
1606 ModuleImport::getConstantsToConvert(llvm::Constant *constant) {
1607  // Return the empty set if the constant has been translated before.
1608  if (valueMapping.contains(constant))
1609  return {};
1610 
1611  // Traverse the constants in post-order and stop the traversal if a constant
1612  // already has a `valueMapping` from an earlier constant translation or if the
1613  // constant is traversed a second time.
1614  SetVector<llvm::Constant *> orderedSet;
1615  SetVector<llvm::Constant *> workList;
1617  workList.insert(constant);
1618  while (!workList.empty()) {
1619  llvm::Constant *current = workList.back();
1620  // References of global objects are just pointers to the object. Avoid
1621  // walking the elements of these here.
1622  if (isa<llvm::GlobalObject>(current) || isa<llvm::GlobalAlias>(current)) {
1623  orderedSet.insert(current);
1624  workList.pop_back();
1625  continue;
1626  }
1627 
1628  // Collect all dependencies of the current constant and add them to the
1629  // adjacency list if none has been computed before.
1630  auto [adjacencyIt, inserted] = adjacencyLists.try_emplace(current);
1631  if (inserted) {
1632  // Add all constant operands to the adjacency list and skip any other
1633  // values such as basic block addresses.
1634  for (llvm::Value *operand : current->operands())
1635  if (auto *constDependency = dyn_cast<llvm::Constant>(operand))
1636  adjacencyIt->getSecond().push_back(constDependency);
1637  // Use the getElementValue method to add the dependencies of zero
1638  // initialized aggregate constants since they do not take any operands.
1639  if (auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(current)) {
1640  unsigned numElements = constAgg->getElementCount().getFixedValue();
1641  for (unsigned i = 0, e = numElements; i != e; ++i)
1642  adjacencyIt->getSecond().push_back(constAgg->getElementValue(i));
1643  }
1644  }
1645  // Add the current constant to the `orderedSet` of the traversed nodes if
1646  // all its dependencies have been traversed before. Additionally, remove the
1647  // constant from the `workList` and continue the traversal.
1648  if (adjacencyIt->getSecond().empty()) {
1649  orderedSet.insert(current);
1650  workList.pop_back();
1651  continue;
1652  }
1653  // Add the next dependency from the adjacency list to the `workList` and
1654  // continue the traversal. Remove the dependency from the adjacency list to
1655  // mark that it has been processed. Only enqueue the dependency if it has no
1656  // `valueMapping` from an earlier translation and if it has not been
1657  // enqueued before.
1658  llvm::Constant *dependency = adjacencyIt->getSecond().pop_back_val();
1659  if (valueMapping.contains(dependency) || workList.contains(dependency) ||
1660  orderedSet.contains(dependency))
1661  continue;
1662  workList.insert(dependency);
1663  }
1664 
1665  return orderedSet;
1666 }
1667 
1668 FailureOr<Value> ModuleImport::convertConstant(llvm::Constant *constant) {
1669  Location loc = UnknownLoc::get(context);
1670 
1671  // Convert constants that can be represented as attributes.
1672  if (Attribute attr = getConstantAsAttr(constant)) {
1673  Type type = convertType(constant->getType());
1674  if (auto symbolRef = dyn_cast<FlatSymbolRefAttr>(attr)) {
1675  return AddressOfOp::create(builder, loc, type, symbolRef.getValue())
1676  .getResult();
1677  }
1678  return ConstantOp::create(builder, loc, type, attr).getResult();
1679  }
1680 
1681  // Convert null pointer constants.
1682  if (auto *nullPtr = dyn_cast<llvm::ConstantPointerNull>(constant)) {
1683  Type type = convertType(nullPtr->getType());
1684  return ZeroOp::create(builder, loc, type).getResult();
1685  }
1686 
1687  // Convert none token constants.
1688  if (isa<llvm::ConstantTokenNone>(constant)) {
1689  return NoneTokenOp::create(builder, loc).getResult();
1690  }
1691 
1692  // Convert poison.
1693  if (auto *poisonVal = dyn_cast<llvm::PoisonValue>(constant)) {
1694  Type type = convertType(poisonVal->getType());
1695  return PoisonOp::create(builder, loc, type).getResult();
1696  }
1697 
1698  // Convert undef.
1699  if (auto *undefVal = dyn_cast<llvm::UndefValue>(constant)) {
1700  Type type = convertType(undefVal->getType());
1701  return UndefOp::create(builder, loc, type).getResult();
1702  }
1703 
1704  // Convert dso_local_equivalent.
1705  if (auto *dsoLocalEquivalent = dyn_cast<llvm::DSOLocalEquivalent>(constant)) {
1706  Type type = convertType(dsoLocalEquivalent->getType());
1707  return DSOLocalEquivalentOp::create(
1708  builder, loc, type,
1710  builder.getContext(),
1711  dsoLocalEquivalent->getGlobalValue()->getName()))
1712  .getResult();
1713  }
1714 
1715  // Convert global variable accesses.
1716  if (auto *globalObj = dyn_cast<llvm::GlobalObject>(constant)) {
1717  Type type = convertType(globalObj->getType());
1718  StringRef globalName = globalObj->getName();
1719  FlatSymbolRefAttr symbolRef;
1720  // Empty names are only allowed for global variables.
1721  if (globalName.empty())
1722  symbolRef =
1723  getOrCreateNamelessSymbolName(cast<llvm::GlobalVariable>(globalObj));
1724  else
1725  symbolRef = FlatSymbolRefAttr::get(context, globalName);
1726  return AddressOfOp::create(builder, loc, type, symbolRef).getResult();
1727  }
1728 
1729  // Convert global alias accesses.
1730  if (auto *globalAliasObj = dyn_cast<llvm::GlobalAlias>(constant)) {
1731  Type type = convertType(globalAliasObj->getType());
1732  StringRef aliaseeName = globalAliasObj->getName();
1733  FlatSymbolRefAttr symbolRef = FlatSymbolRefAttr::get(context, aliaseeName);
1734  return AddressOfOp::create(builder, loc, type, symbolRef).getResult();
1735  }
1736 
1737  // Convert constant expressions.
1738  if (auto *constExpr = dyn_cast<llvm::ConstantExpr>(constant)) {
1739  // Convert the constant expression to a temporary LLVM instruction and
1740  // translate it using the `processInstruction` method. Delete the
1741  // instruction after the translation and remove it from `valueMapping`,
1742  // since later calls to `getAsInstruction` may return the same address
1743  // resulting in a conflicting `valueMapping` entry.
1744  llvm::Instruction *inst = constExpr->getAsInstruction();
1745  auto guard = llvm::make_scope_exit([&]() {
1746  assert(!noResultOpMapping.contains(inst) &&
1747  "expected constant expression to return a result");
1748  valueMapping.erase(inst);
1749  inst->deleteValue();
1750  });
1751  // Note: `processInstruction` does not call `convertConstant` recursively
1752  // since all constant dependencies have been converted before.
1753  assert(llvm::all_of(inst->operands(), [&](llvm::Value *value) {
1754  return valueMapping.contains(value);
1755  }));
1756  if (failed(processInstruction(inst)))
1757  return failure();
1758  return lookupValue(inst);
1759  }
1760 
1761  // Convert aggregate constants.
1762  if (isa<llvm::ConstantAggregate>(constant) ||
1763  isa<llvm::ConstantAggregateZero>(constant)) {
1764  // Lookup the aggregate elements that have been converted before.
1765  SmallVector<Value> elementValues;
1766  if (auto *constAgg = dyn_cast<llvm::ConstantAggregate>(constant)) {
1767  elementValues.reserve(constAgg->getNumOperands());
1768  for (llvm::Value *operand : constAgg->operands())
1769  elementValues.push_back(lookupValue(operand));
1770  }
1771  if (auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1772  unsigned numElements = constAgg->getElementCount().getFixedValue();
1773  elementValues.reserve(numElements);
1774  for (unsigned i = 0, e = numElements; i != e; ++i)
1775  elementValues.push_back(lookupValue(constAgg->getElementValue(i)));
1776  }
1777  assert(llvm::count(elementValues, nullptr) == 0 &&
1778  "expected all elements have been converted before");
1779 
1780  // Generate an UndefOp as root value and insert the aggregate elements.
1781  Type rootType = convertType(constant->getType());
1782  bool isArrayOrStruct = isa<LLVMArrayType, LLVMStructType>(rootType);
1783  assert((isArrayOrStruct || LLVM::isCompatibleVectorType(rootType)) &&
1784  "unrecognized aggregate type");
1785  Value root = UndefOp::create(builder, loc, rootType);
1786  for (const auto &it : llvm::enumerate(elementValues)) {
1787  if (isArrayOrStruct) {
1788  root =
1789  InsertValueOp::create(builder, loc, root, it.value(), it.index());
1790  } else {
1791  Attribute indexAttr = builder.getI32IntegerAttr(it.index());
1792  Value indexValue =
1793  ConstantOp::create(builder, loc, builder.getI32Type(), indexAttr);
1794  root = InsertElementOp::create(builder, loc, rootType, root, it.value(),
1795  indexValue);
1796  }
1797  }
1798  return root;
1799  }
1800 
1801  if (auto *constTargetNone = dyn_cast<llvm::ConstantTargetNone>(constant)) {
1802  LLVMTargetExtType targetExtType =
1803  cast<LLVMTargetExtType>(convertType(constTargetNone->getType()));
1804  assert(targetExtType.hasProperty(LLVMTargetExtType::HasZeroInit) &&
1805  "target extension type does not support zero-initialization");
1806  // Create llvm.mlir.zero operation to represent zero-initialization of
1807  // target extension type.
1808  return LLVM::ZeroOp::create(builder, loc, targetExtType).getRes();
1809  }
1810 
1811  if (auto *blockAddr = dyn_cast<llvm::BlockAddress>(constant)) {
1812  auto fnSym =
1813  FlatSymbolRefAttr::get(context, blockAddr->getFunction()->getName());
1814  auto blockTag =
1815  BlockTagAttr::get(context, blockAddr->getBasicBlock()->getNumber());
1816  return BlockAddressOp::create(
1817  builder, loc, convertType(blockAddr->getType()),
1818  BlockAddressAttr::get(context, fnSym, blockTag))
1819  .getRes();
1820  }
1821 
1822  StringRef error = "";
1823 
1824  if (isa<llvm::ConstantPtrAuth>(constant))
1825  error = " since ptrauth(...) is unsupported";
1826 
1827  if (isa<llvm::NoCFIValue>(constant))
1828  error = " since no_cfi is unsupported";
1829 
1830  if (isa<llvm::GlobalValue>(constant))
1831  error = " since global value is unsupported";
1832 
1833  return emitError(loc) << "unhandled constant: " << diag(*constant) << error;
1834 }
1835 
1836 FailureOr<Value> ModuleImport::convertConstantExpr(llvm::Constant *constant) {
1837  // Only call the function for constants that have not been translated before
1838  // since it updates the constant insertion point assuming the converted
1839  // constant has been introduced at the end of the constant section.
1840  assert(!valueMapping.contains(constant) &&
1841  "expected constant has not been converted before");
1842  assert(constantInsertionBlock &&
1843  "expected the constant insertion block to be non-null");
1844 
1845  // Insert the constant after the last one or at the start of the entry block.
1846  OpBuilder::InsertionGuard guard(builder);
1847  if (!constantInsertionOp)
1848  builder.setInsertionPointToStart(constantInsertionBlock);
1849  else
1850  builder.setInsertionPointAfter(constantInsertionOp);
1851 
1852  // Convert all constants of the expression and add them to `valueMapping`.
1853  SetVector<llvm::Constant *> constantsToConvert =
1854  getConstantsToConvert(constant);
1855  for (llvm::Constant *constantToConvert : constantsToConvert) {
1856  FailureOr<Value> converted = convertConstant(constantToConvert);
1857  if (failed(converted))
1858  return failure();
1859  mapValue(constantToConvert, *converted);
1860  }
1861 
1862  // Update the constant insertion point and return the converted constant.
1863  Value result = lookupValue(constant);
1864  constantInsertionOp = result.getDefiningOp();
1865  return result;
1866 }
1867 
1868 FailureOr<Value> ModuleImport::convertValue(llvm::Value *value) {
1869  assert(!isa<llvm::MetadataAsValue>(value) &&
1870  "expected value to not be metadata");
1871 
1872  // Return the mapped value if it has been converted before.
1873  auto it = valueMapping.find(value);
1874  if (it != valueMapping.end())
1875  return it->getSecond();
1876 
1877  // Convert constants such as immediate values that have no mapping yet.
1878  if (auto *constant = dyn_cast<llvm::Constant>(value))
1879  return convertConstantExpr(constant);
1880 
1881  Location loc = UnknownLoc::get(context);
1882  if (auto *inst = dyn_cast<llvm::Instruction>(value))
1883  loc = translateLoc(inst->getDebugLoc());
1884  return emitError(loc) << "unhandled value: " << diag(*value);
1885 }
1886 
1887 FailureOr<Value> ModuleImport::convertMetadataValue(llvm::Value *value) {
1888  // A value may be wrapped as metadata, for example, when passed to a debug
1889  // intrinsic. Unwrap these values before the conversion.
1890  auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
1891  if (!nodeAsVal)
1892  return failure();
1893  auto *node = dyn_cast<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
1894  if (!node)
1895  return failure();
1896  value = node->getValue();
1897 
1898  // Return the mapped value if it has been converted before.
1899  auto it = valueMapping.find(value);
1900  if (it != valueMapping.end())
1901  return it->getSecond();
1902 
1903  // Convert constants such as immediate values that have no mapping yet.
1904  if (auto *constant = dyn_cast<llvm::Constant>(value))
1905  return convertConstantExpr(constant);
1906  return failure();
1907 }
1908 
1909 FailureOr<SmallVector<Value>>
1911  SmallVector<Value> remapped;
1912  remapped.reserve(values.size());
1913  for (llvm::Value *value : values) {
1914  FailureOr<Value> converted = convertValue(value);
1915  if (failed(converted))
1916  return failure();
1917  remapped.push_back(*converted);
1918  }
1919  return remapped;
1920 }
1921 
1924  bool requiresOpBundles, ArrayRef<unsigned> immArgPositions,
1925  ArrayRef<StringLiteral> immArgAttrNames, SmallVectorImpl<Value> &valuesOut,
1926  SmallVectorImpl<NamedAttribute> &attrsOut) {
1927  assert(immArgPositions.size() == immArgAttrNames.size() &&
1928  "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "
1929  "length");
1930 
1931  SmallVector<llvm::Value *> operands(values);
1932  for (auto [immArgPos, immArgName] :
1933  llvm::zip(immArgPositions, immArgAttrNames)) {
1934  auto &value = operands[immArgPos];
1935  auto *constant = llvm::cast<llvm::Constant>(value);
1936  auto attr = getScalarConstantAsAttr(builder, constant);
1937  assert(attr && attr.getType().isIntOrFloat() &&
1938  "expected immarg to be float or integer constant");
1939  auto nameAttr = StringAttr::get(attr.getContext(), immArgName);
1940  attrsOut.push_back({nameAttr, attr});
1941  // Mark matched attribute values as null (so they can be removed below).
1942  value = nullptr;
1943  }
1944 
1945  for (llvm::Value *value : operands) {
1946  if (!value)
1947  continue;
1948  auto mlirValue = convertValue(value);
1949  if (failed(mlirValue))
1950  return failure();
1951  valuesOut.push_back(*mlirValue);
1952  }
1953 
1954  SmallVector<int> opBundleSizes;
1955  SmallVector<Attribute> opBundleTagAttrs;
1956  if (requiresOpBundles) {
1957  opBundleSizes.reserve(opBundles.size());
1958  opBundleTagAttrs.reserve(opBundles.size());
1959 
1960  for (const llvm::OperandBundleUse &bundle : opBundles) {
1961  opBundleSizes.push_back(bundle.Inputs.size());
1962  opBundleTagAttrs.push_back(StringAttr::get(context, bundle.getTagName()));
1963 
1964  for (const llvm::Use &opBundleOperand : bundle.Inputs) {
1965  auto operandMlirValue = convertValue(opBundleOperand.get());
1966  if (failed(operandMlirValue))
1967  return failure();
1968  valuesOut.push_back(*operandMlirValue);
1969  }
1970  }
1971 
1972  auto opBundleSizesAttr = DenseI32ArrayAttr::get(context, opBundleSizes);
1973  auto opBundleSizesAttrNameAttr =
1974  StringAttr::get(context, LLVMDialect::getOpBundleSizesAttrName());
1975  attrsOut.push_back({opBundleSizesAttrNameAttr, opBundleSizesAttr});
1976 
1977  auto opBundleTagsAttr = ArrayAttr::get(context, opBundleTagAttrs);
1978  auto opBundleTagsAttrNameAttr =
1979  StringAttr::get(context, LLVMDialect::getOpBundleTagsAttrName());
1980  attrsOut.push_back({opBundleTagsAttrNameAttr, opBundleTagsAttr});
1981  }
1982 
1983  return success();
1984 }
1985 
1986 IntegerAttr ModuleImport::matchIntegerAttr(llvm::Value *value) {
1987  IntegerAttr integerAttr;
1988  FailureOr<Value> converted = convertValue(value);
1989  bool success = succeeded(converted) &&
1990  matchPattern(*converted, m_Constant(&integerAttr));
1991  assert(success && "expected a constant integer value");
1992  (void)success;
1993  return integerAttr;
1994 }
1995 
1996 FloatAttr ModuleImport::matchFloatAttr(llvm::Value *value) {
1997  FloatAttr floatAttr;
1998  FailureOr<Value> converted = convertValue(value);
1999  bool success =
2000  succeeded(converted) && matchPattern(*converted, m_Constant(&floatAttr));
2001  assert(success && "expected a constant float value");
2002  (void)success;
2003  return floatAttr;
2004 }
2005 
2006 DILocalVariableAttr ModuleImport::matchLocalVariableAttr(llvm::Value *value) {
2007  auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2008  auto *node = cast<llvm::DILocalVariable>(nodeAsVal->getMetadata());
2009  return debugImporter->translate(node);
2010 }
2011 
2012 DILabelAttr ModuleImport::matchLabelAttr(llvm::Value *value) {
2013  auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2014  auto *node = cast<llvm::DILabel>(nodeAsVal->getMetadata());
2015  return debugImporter->translate(node);
2016 }
2017 
2018 FPExceptionBehaviorAttr
2020  auto *metadata = cast<llvm::MetadataAsValue>(value);
2021  auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
2022  std::optional<llvm::fp::ExceptionBehavior> optLLVM =
2023  llvm::convertStrToExceptionBehavior(mdstr->getString());
2024  assert(optLLVM && "Expecting FP exception behavior");
2025  return builder.getAttr<FPExceptionBehaviorAttr>(
2026  convertFPExceptionBehaviorFromLLVM(*optLLVM));
2027 }
2028 
2029 RoundingModeAttr ModuleImport::matchRoundingModeAttr(llvm::Value *value) {
2030  auto *metadata = cast<llvm::MetadataAsValue>(value);
2031  auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
2032  std::optional<llvm::RoundingMode> optLLVM =
2033  llvm::convertStrToRoundingMode(mdstr->getString());
2034  assert(optLLVM && "Expecting rounding mode");
2035  return builder.getAttr<RoundingModeAttr>(
2036  convertRoundingModeFromLLVM(*optLLVM));
2037 }
2038 
2039 FailureOr<SmallVector<AliasScopeAttr>>
2041  auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2042  auto *node = cast<llvm::MDNode>(nodeAsVal->getMetadata());
2043  return lookupAliasScopeAttrs(node);
2044 }
2045 
2046 Location ModuleImport::translateLoc(llvm::DILocation *loc) {
2047  return debugImporter->translateLoc(loc);
2048 }
2049 
2050 LogicalResult
2051 ModuleImport::convertBranchArgs(llvm::Instruction *branch,
2052  llvm::BasicBlock *target,
2053  SmallVectorImpl<Value> &blockArguments) {
2054  for (auto inst = target->begin(); isa<llvm::PHINode>(inst); ++inst) {
2055  auto *phiInst = cast<llvm::PHINode>(&*inst);
2056  llvm::Value *value = phiInst->getIncomingValueForBlock(branch->getParent());
2057  FailureOr<Value> converted = convertValue(value);
2058  if (failed(converted))
2059  return failure();
2060  blockArguments.push_back(*converted);
2061  }
2062  return success();
2063 }
2064 
2065 FailureOr<SmallVector<Value>>
2066 ModuleImport::convertCallOperands(llvm::CallBase *callInst,
2067  bool allowInlineAsm) {
2068  bool isInlineAsm = callInst->isInlineAsm();
2069  if (isInlineAsm && !allowInlineAsm)
2070  return failure();
2071 
2072  SmallVector<Value> operands;
2073 
2074  // Cannot use isIndirectCall() here because we need to handle Constant callees
2075  // that are not considered indirect calls by LLVM. However, in MLIR, they are
2076  // treated as indirect calls to constant operands that need to be converted.
2077  // Skip the callee operand if it's inline assembly, as it's handled separately
2078  // in InlineAsmOp.
2079  llvm::Value *calleeOperand = callInst->getCalledOperand();
2080  if (!isa<llvm::Function, llvm::GlobalIFunc>(calleeOperand) && !isInlineAsm) {
2081  FailureOr<Value> called = convertValue(calleeOperand);
2082  if (failed(called))
2083  return failure();
2084  operands.push_back(*called);
2085  }
2086 
2087  SmallVector<llvm::Value *> args(callInst->args());
2088  FailureOr<SmallVector<Value>> arguments = convertValues(args);
2089  if (failed(arguments))
2090  return failure();
2091 
2092  llvm::append_range(operands, *arguments);
2093  return operands;
2094 }
2095 
2096 /// Checks if `callType` and `calleeType` are compatible and can be represented
2097 /// in MLIR.
2098 static LogicalResult
2099 checkFunctionTypeCompatibility(LLVMFunctionType callType,
2100  LLVMFunctionType calleeType) {
2101  if (callType.getReturnType() != calleeType.getReturnType())
2102  return failure();
2103 
2104  if (calleeType.isVarArg()) {
2105  // For variadic functions, the call can have more types than the callee
2106  // specifies.
2107  if (callType.getNumParams() < calleeType.getNumParams())
2108  return failure();
2109  } else {
2110  // For non-variadic functions, the number of parameters needs to be the
2111  // same.
2112  if (callType.getNumParams() != calleeType.getNumParams())
2113  return failure();
2114  }
2115 
2116  // Check that all operands match.
2117  for (auto [operandType, argumentType] :
2118  llvm::zip(callType.getParams(), calleeType.getParams()))
2119  if (operandType != argumentType)
2120  return failure();
2121 
2122  return success();
2123 }
2124 
2125 FailureOr<LLVMFunctionType>
2126 ModuleImport::convertFunctionType(llvm::CallBase *callInst,
2127  bool &isIncompatibleCall) {
2128  isIncompatibleCall = false;
2129  auto castOrFailure = [](Type convertedType) -> FailureOr<LLVMFunctionType> {
2130  auto funcTy = dyn_cast_or_null<LLVMFunctionType>(convertedType);
2131  if (!funcTy)
2132  return failure();
2133  return funcTy;
2134  };
2135 
2136  llvm::Value *calledOperand = callInst->getCalledOperand();
2137  FailureOr<LLVMFunctionType> callType =
2138  castOrFailure(convertType(callInst->getFunctionType()));
2139  if (failed(callType))
2140  return failure();
2141  auto *callee = dyn_cast<llvm::Function>(calledOperand);
2142 
2143  llvm::FunctionType *origCalleeType = nullptr;
2144  if (callee) {
2145  origCalleeType = callee->getFunctionType();
2146  } else if (auto *ifunc = dyn_cast<llvm::GlobalIFunc>(calledOperand)) {
2147  origCalleeType = cast<llvm::FunctionType>(ifunc->getValueType());
2148  }
2149 
2150  // For indirect calls, return the type of the call itself.
2151  if (!origCalleeType)
2152  return callType;
2153 
2154  FailureOr<LLVMFunctionType> calleeType =
2155  castOrFailure(convertType(origCalleeType));
2156  if (failed(calleeType))
2157  return failure();
2158 
2159  // Compare the types and notify users via `isIncompatibleCall` if they are not
2160  // compatible.
2161  if (failed(checkFunctionTypeCompatibility(*callType, *calleeType))) {
2162  isIncompatibleCall = true;
2163  Location loc = translateLoc(callInst->getDebugLoc());
2164  emitWarning(loc) << "incompatible call and callee types: " << *callType
2165  << " and " << *calleeType;
2166  return callType;
2167  }
2168 
2169  return calleeType;
2170 }
2171 
2172 FlatSymbolRefAttr ModuleImport::convertCalleeName(llvm::CallBase *callInst) {
2173  llvm::Value *calledOperand = callInst->getCalledOperand();
2174  if (isa<llvm::Function, llvm::GlobalIFunc>(calledOperand))
2175  return SymbolRefAttr::get(context, calledOperand->getName());
2176  return {};
2177 }
2178 
2179 LogicalResult ModuleImport::convertIntrinsic(llvm::CallInst *inst) {
2180  if (succeeded(iface.convertIntrinsic(builder, inst, *this)))
2181  return success();
2182 
2183  Location loc = translateLoc(inst->getDebugLoc());
2184  return emitError(loc) << "unhandled intrinsic: " << diag(*inst);
2185 }
2186 
2187 ArrayAttr
2188 ModuleImport::convertAsmInlineOperandAttrs(const llvm::CallBase &llvmCall) {
2189  const auto *ia = cast<llvm::InlineAsm>(llvmCall.getCalledOperand());
2190  unsigned argIdx = 0;
2192  bool hasIndirect = false;
2193 
2194  for (const llvm::InlineAsm::ConstraintInfo &ci : ia->ParseConstraints()) {
2195  // Only deal with constraints that correspond to call arguments.
2196  if (ci.Type == llvm::InlineAsm::isLabel || !ci.hasArg())
2197  continue;
2198 
2199  // Only increment `argIdx` in terms of constraints containing arguments,
2200  // which are guaranteed to happen in the same order of the call arguments.
2201  if (ci.isIndirect) {
2202  if (llvm::Type *paramEltType = llvmCall.getParamElementType(argIdx)) {
2204  attrs.push_back(builder.getNamedAttr(
2205  mlir::LLVM::InlineAsmOp::getElementTypeAttrName(),
2206  mlir::TypeAttr::get(convertType(paramEltType))));
2207  opAttrs.push_back(builder.getDictionaryAttr(attrs));
2208  hasIndirect = true;
2209  }
2210  } else {
2211  opAttrs.push_back(builder.getDictionaryAttr({}));
2212  }
2213  argIdx++;
2214  }
2215 
2216  // Avoid emitting an array where all entries are empty dictionaries.
2217  return hasIndirect ? ArrayAttr::get(mlirModule->getContext(), opAttrs)
2218  : nullptr;
2219 }
2220 
2221 LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
2222  // Convert all instructions that do not provide an MLIR builder.
2223  Location loc = translateLoc(inst->getDebugLoc());
2224  if (inst->getOpcode() == llvm::Instruction::Br) {
2225  auto *brInst = cast<llvm::BranchInst>(inst);
2226 
2227  SmallVector<Block *> succBlocks;
2228  SmallVector<SmallVector<Value>> succBlockArgs;
2229  for (auto i : llvm::seq<unsigned>(0, brInst->getNumSuccessors())) {
2230  llvm::BasicBlock *succ = brInst->getSuccessor(i);
2231  SmallVector<Value> blockArgs;
2232  if (failed(convertBranchArgs(brInst, succ, blockArgs)))
2233  return failure();
2234  succBlocks.push_back(lookupBlock(succ));
2235  succBlockArgs.push_back(blockArgs);
2236  }
2237 
2238  if (!brInst->isConditional()) {
2239  auto brOp = LLVM::BrOp::create(builder, loc, succBlockArgs.front(),
2240  succBlocks.front());
2241  mapNoResultOp(inst, brOp);
2242  return success();
2243  }
2244  FailureOr<Value> condition = convertValue(brInst->getCondition());
2245  if (failed(condition))
2246  return failure();
2247  auto condBrOp = LLVM::CondBrOp::create(
2248  builder, loc, *condition, succBlocks.front(), succBlockArgs.front(),
2249  succBlocks.back(), succBlockArgs.back());
2250  mapNoResultOp(inst, condBrOp);
2251  return success();
2252  }
2253  if (inst->getOpcode() == llvm::Instruction::Switch) {
2254  auto *swInst = cast<llvm::SwitchInst>(inst);
2255  // Process the condition value.
2256  FailureOr<Value> condition = convertValue(swInst->getCondition());
2257  if (failed(condition))
2258  return failure();
2259  SmallVector<Value> defaultBlockArgs;
2260  // Process the default case.
2261  llvm::BasicBlock *defaultBB = swInst->getDefaultDest();
2262  if (failed(convertBranchArgs(swInst, defaultBB, defaultBlockArgs)))
2263  return failure();
2264 
2265  // Process the cases.
2266  unsigned numCases = swInst->getNumCases();
2267  SmallVector<SmallVector<Value>> caseOperands(numCases);
2268  SmallVector<ValueRange> caseOperandRefs(numCases);
2269  SmallVector<APInt> caseValues(numCases);
2270  SmallVector<Block *> caseBlocks(numCases);
2271  for (const auto &it : llvm::enumerate(swInst->cases())) {
2272  const llvm::SwitchInst::CaseHandle &caseHandle = it.value();
2273  llvm::BasicBlock *succBB = caseHandle.getCaseSuccessor();
2274  if (failed(convertBranchArgs(swInst, succBB, caseOperands[it.index()])))
2275  return failure();
2276  caseOperandRefs[it.index()] = caseOperands[it.index()];
2277  caseValues[it.index()] = caseHandle.getCaseValue()->getValue();
2278  caseBlocks[it.index()] = lookupBlock(succBB);
2279  }
2280 
2281  auto switchOp = SwitchOp::create(builder, loc, *condition,
2282  lookupBlock(defaultBB), defaultBlockArgs,
2283  caseValues, caseBlocks, caseOperandRefs);
2284  mapNoResultOp(inst, switchOp);
2285  return success();
2286  }
2287  if (inst->getOpcode() == llvm::Instruction::PHI) {
2288  Type type = convertType(inst->getType());
2289  mapValue(inst, builder.getInsertionBlock()->addArgument(
2290  type, translateLoc(inst->getDebugLoc())));
2291  return success();
2292  }
2293  if (inst->getOpcode() == llvm::Instruction::Call) {
2294  auto *callInst = cast<llvm::CallInst>(inst);
2295  llvm::Value *calledOperand = callInst->getCalledOperand();
2296 
2297  FailureOr<SmallVector<Value>> operands =
2298  convertCallOperands(callInst, /*allowInlineAsm=*/true);
2299  if (failed(operands))
2300  return failure();
2301 
2302  auto callOp = [&]() -> FailureOr<Operation *> {
2303  if (auto *asmI = dyn_cast<llvm::InlineAsm>(calledOperand)) {
2304  Type resultTy = convertType(callInst->getType());
2305  if (!resultTy)
2306  return failure();
2307  ArrayAttr operandAttrs = convertAsmInlineOperandAttrs(*callInst);
2308  return InlineAsmOp::create(
2309  builder, loc, resultTy, *operands,
2310  builder.getStringAttr(asmI->getAsmString()),
2311  builder.getStringAttr(asmI->getConstraintString()),
2312  asmI->hasSideEffects(), asmI->isAlignStack(),
2313  convertTailCallKindFromLLVM(callInst->getTailCallKind()),
2315  mlirModule.getContext(),
2316  convertAsmDialectFromLLVM(asmI->getDialect())),
2317  operandAttrs)
2318  .getOperation();
2319  }
2320  bool isIncompatibleCall;
2321  FailureOr<LLVMFunctionType> funcTy =
2322  convertFunctionType(callInst, isIncompatibleCall);
2323  if (failed(funcTy))
2324  return failure();
2325 
2326  FlatSymbolRefAttr callee = nullptr;
2327  if (isIncompatibleCall) {
2328  // Use an indirect call (in order to represent valid and verifiable LLVM
2329  // IR). Build the indirect call by passing an empty `callee` operand and
2330  // insert into `operands` to include the indirect call target.
2331  FlatSymbolRefAttr calleeSym = convertCalleeName(callInst);
2332  Value indirectCallVal = LLVM::AddressOfOp::create(
2333  builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);
2334  operands->insert(operands->begin(), indirectCallVal);
2335  } else {
2336  // Regular direct call using callee name.
2337  callee = convertCalleeName(callInst);
2338  }
2339  CallOp callOp = CallOp::create(builder, loc, *funcTy, callee, *operands);
2340 
2341  if (failed(convertCallAttributes(callInst, callOp)))
2342  return failure();
2343 
2344  // Handle parameter and result attributes unless it's an incompatible
2345  // call.
2346  if (!isIncompatibleCall)
2347  convertArgAndResultAttrs(callInst, callOp);
2348  return callOp.getOperation();
2349  }();
2350 
2351  if (failed(callOp))
2352  return failure();
2353 
2354  if (!callInst->getType()->isVoidTy())
2355  mapValue(inst, (*callOp)->getResult(0));
2356  else
2357  mapNoResultOp(inst, *callOp);
2358  return success();
2359  }
2360  if (inst->getOpcode() == llvm::Instruction::LandingPad) {
2361  auto *lpInst = cast<llvm::LandingPadInst>(inst);
2362 
2363  SmallVector<Value> operands;
2364  operands.reserve(lpInst->getNumClauses());
2365  for (auto i : llvm::seq<unsigned>(0, lpInst->getNumClauses())) {
2366  FailureOr<Value> operand = convertValue(lpInst->getClause(i));
2367  if (failed(operand))
2368  return failure();
2369  operands.push_back(*operand);
2370  }
2371 
2372  Type type = convertType(lpInst->getType());
2373  auto lpOp =
2374  LandingpadOp::create(builder, loc, type, lpInst->isCleanup(), operands);
2375  mapValue(inst, lpOp);
2376  return success();
2377  }
2378  if (inst->getOpcode() == llvm::Instruction::Invoke) {
2379  auto *invokeInst = cast<llvm::InvokeInst>(inst);
2380 
2381  if (invokeInst->isInlineAsm())
2382  return emitError(loc) << "invoke of inline assembly is not supported";
2383 
2384  FailureOr<SmallVector<Value>> operands = convertCallOperands(invokeInst);
2385  if (failed(operands))
2386  return failure();
2387 
2388  // Check whether the invoke result is an argument to the normal destination
2389  // block.
2390  bool invokeResultUsedInPhi = llvm::any_of(
2391  invokeInst->getNormalDest()->phis(), [&](const llvm::PHINode &phi) {
2392  return phi.getIncomingValueForBlock(invokeInst->getParent()) ==
2393  invokeInst;
2394  });
2395 
2396  Block *normalDest = lookupBlock(invokeInst->getNormalDest());
2397  Block *directNormalDest = normalDest;
2398  if (invokeResultUsedInPhi) {
2399  // The invoke result cannot be an argument to the normal destination
2400  // block, as that would imply using the invoke operation result in its
2401  // definition, so we need to create a dummy block to serve as an
2402  // intermediate destination.
2403  OpBuilder::InsertionGuard g(builder);
2404  directNormalDest = builder.createBlock(normalDest);
2405  }
2406 
2407  SmallVector<Value> unwindArgs;
2408  if (failed(convertBranchArgs(invokeInst, invokeInst->getUnwindDest(),
2409  unwindArgs)))
2410  return failure();
2411 
2412  bool isIncompatibleInvoke;
2413  FailureOr<LLVMFunctionType> funcTy =
2414  convertFunctionType(invokeInst, isIncompatibleInvoke);
2415  if (failed(funcTy))
2416  return failure();
2417 
2418  FlatSymbolRefAttr calleeName = nullptr;
2419  if (isIncompatibleInvoke) {
2420  // Use an indirect invoke (in order to represent valid and verifiable LLVM
2421  // IR). Build the indirect invoke by passing an empty `callee` operand and
2422  // insert into `operands` to include the indirect invoke target.
2423  FlatSymbolRefAttr calleeSym = convertCalleeName(invokeInst);
2424  Value indirectInvokeVal = LLVM::AddressOfOp::create(
2425  builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);
2426  operands->insert(operands->begin(), indirectInvokeVal);
2427  } else {
2428  // Regular direct invoke using callee name.
2429  calleeName = convertCalleeName(invokeInst);
2430  }
2431  // Create the invoke operation. Normal destination block arguments will be
2432  // added later on to handle the case in which the operation result is
2433  // included in this list.
2434  auto invokeOp = InvokeOp::create(
2435  builder, loc, *funcTy, calleeName, *operands, directNormalDest,
2436  ValueRange(), lookupBlock(invokeInst->getUnwindDest()), unwindArgs);
2437 
2438  if (failed(convertInvokeAttributes(invokeInst, invokeOp)))
2439  return failure();
2440 
2441  // Handle parameter and result attributes unless it's an incompatible
2442  // invoke.
2443  if (!isIncompatibleInvoke)
2444  convertArgAndResultAttrs(invokeInst, invokeOp);
2445 
2446  if (!invokeInst->getType()->isVoidTy())
2447  mapValue(inst, invokeOp.getResults().front());
2448  else
2449  mapNoResultOp(inst, invokeOp);
2450 
2451  SmallVector<Value> normalArgs;
2452  if (failed(convertBranchArgs(invokeInst, invokeInst->getNormalDest(),
2453  normalArgs)))
2454  return failure();
2455 
2456  if (invokeResultUsedInPhi) {
2457  // The dummy normal dest block will just host an unconditional branch
2458  // instruction to the normal destination block passing the required block
2459  // arguments (including the invoke operation's result).
2460  OpBuilder::InsertionGuard g(builder);
2461  builder.setInsertionPointToStart(directNormalDest);
2462  LLVM::BrOp::create(builder, loc, normalArgs, normalDest);
2463  } else {
2464  // If the invoke operation's result is not a block argument to the normal
2465  // destination block, just add the block arguments as usual.
2466  assert(llvm::none_of(
2467  normalArgs,
2468  [&](Value val) { return val.getDefiningOp() == invokeOp; }) &&
2469  "An llvm.invoke operation cannot pass its result as a block "
2470  "argument.");
2471  invokeOp.getNormalDestOperandsMutable().append(normalArgs);
2472  }
2473 
2474  return success();
2475  }
2476  if (inst->getOpcode() == llvm::Instruction::GetElementPtr) {
2477  auto *gepInst = cast<llvm::GetElementPtrInst>(inst);
2478  Type sourceElementType = convertType(gepInst->getSourceElementType());
2479  FailureOr<Value> basePtr = convertValue(gepInst->getOperand(0));
2480  if (failed(basePtr))
2481  return failure();
2482 
2483  // Treat every indices as dynamic since GEPOp::build will refine those
2484  // indices into static attributes later. One small downside of this
2485  // approach is that many unused `llvm.mlir.constant` would be emitted
2486  // at first place.
2487  SmallVector<GEPArg> indices;
2488  for (llvm::Value *operand : llvm::drop_begin(gepInst->operand_values())) {
2489  FailureOr<Value> index = convertValue(operand);
2490  if (failed(index))
2491  return failure();
2492  indices.push_back(*index);
2493  }
2494 
2495  Type type = convertType(inst->getType());
2496  auto gepOp = GEPOp::create(
2497  builder, loc, type, sourceElementType, *basePtr, indices,
2498  static_cast<GEPNoWrapFlags>(gepInst->getNoWrapFlags().getRaw()));
2499  mapValue(inst, gepOp);
2500  return success();
2501  }
2502 
2503  if (inst->getOpcode() == llvm::Instruction::IndirectBr) {
2504  auto *indBrInst = cast<llvm::IndirectBrInst>(inst);
2505 
2506  FailureOr<Value> basePtr = convertValue(indBrInst->getAddress());
2507  if (failed(basePtr))
2508  return failure();
2509 
2510  SmallVector<Block *> succBlocks;
2511  SmallVector<SmallVector<Value>> succBlockArgs;
2512  for (auto i : llvm::seq<unsigned>(0, indBrInst->getNumSuccessors())) {
2513  llvm::BasicBlock *succ = indBrInst->getSuccessor(i);
2514  SmallVector<Value> blockArgs;
2515  if (failed(convertBranchArgs(indBrInst, succ, blockArgs)))
2516  return failure();
2517  succBlocks.push_back(lookupBlock(succ));
2518  succBlockArgs.push_back(blockArgs);
2519  }
2520  SmallVector<ValueRange> succBlockArgsRange =
2521  llvm::to_vector_of<ValueRange>(succBlockArgs);
2522  Location loc = translateLoc(inst->getDebugLoc());
2523  auto indBrOp = LLVM::IndirectBrOp::create(builder, loc, *basePtr,
2524  succBlockArgsRange, succBlocks);
2525 
2526  mapNoResultOp(inst, indBrOp);
2527  return success();
2528  }
2529 
2530  // Convert all instructions that have an mlirBuilder.
2531  if (succeeded(convertInstructionImpl(builder, inst, *this, iface)))
2532  return success();
2533 
2534  return emitError(loc) << "unhandled instruction: " << diag(*inst);
2535 }
2536 
2537 LogicalResult ModuleImport::processInstruction(llvm::Instruction *inst) {
2538  // FIXME: Support uses of SubtargetData.
2539  // FIXME: Add support for call / operand attributes.
2540  // FIXME: Add support for the cleanupret, catchret, catchswitch, callbr,
2541  // vaarg, catchpad, cleanuppad instructions.
2542 
2543  // Convert LLVM intrinsics calls to MLIR intrinsics.
2544  if (auto *intrinsic = dyn_cast<llvm::IntrinsicInst>(inst))
2545  return convertIntrinsic(intrinsic);
2546 
2547  // Convert all remaining LLVM instructions to MLIR operations.
2548  return convertInstruction(inst);
2549 }
2550 
2551 FlatSymbolRefAttr ModuleImport::getPersonalityAsAttr(llvm::Function *f) {
2552  if (!f->hasPersonalityFn())
2553  return nullptr;
2554 
2555  llvm::Constant *pf = f->getPersonalityFn();
2556 
2557  // If it directly has a name, we can use it.
2558  if (pf->hasName())
2559  return SymbolRefAttr::get(builder.getContext(), pf->getName());
2560 
2561  // If it doesn't have a name, currently, only function pointers that are
2562  // bitcast to i8* are parsed.
2563  if (auto *ce = dyn_cast<llvm::ConstantExpr>(pf)) {
2564  if (ce->getOpcode() == llvm::Instruction::BitCast &&
2565  ce->getType() == llvm::PointerType::getUnqual(f->getContext())) {
2566  if (auto *func = dyn_cast<llvm::Function>(ce->getOperand(0)))
2567  return SymbolRefAttr::get(builder.getContext(), func->getName());
2568  }
2569  }
2570  return FlatSymbolRefAttr();
2571 }
2572 
2573 static void processMemoryEffects(llvm::Function *func, LLVMFuncOp funcOp) {
2574  llvm::MemoryEffects memEffects = func->getMemoryEffects();
2575 
2576  auto othermem = convertModRefInfoFromLLVM(
2577  memEffects.getModRef(llvm::MemoryEffects::Location::Other));
2578  auto argMem = convertModRefInfoFromLLVM(
2579  memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
2580  auto inaccessibleMem = convertModRefInfoFromLLVM(
2581  memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
2582  auto memAttr = MemoryEffectsAttr::get(funcOp.getContext(), othermem, argMem,
2583  inaccessibleMem);
2584  // Only set the attr when it does not match the default value.
2585  if (memAttr.isReadWrite())
2586  return;
2587  funcOp.setMemoryEffectsAttr(memAttr);
2588 }
2589 
2590 // List of LLVM IR attributes that map to an explicit attribute on the MLIR
2591 // LLVMFuncOp.
2592 static constexpr std::array kExplicitLLVMFuncOpAttributes{
2593  StringLiteral("aarch64_in_za"),
2594  StringLiteral("aarch64_inout_za"),
2595  StringLiteral("aarch64_new_za"),
2596  StringLiteral("aarch64_out_za"),
2597  StringLiteral("aarch64_preserves_za"),
2598  StringLiteral("aarch64_pstate_sm_body"),
2599  StringLiteral("aarch64_pstate_sm_compatible"),
2600  StringLiteral("aarch64_pstate_sm_enabled"),
2601  StringLiteral("alwaysinline"),
2602  StringLiteral("convergent"),
2603  StringLiteral("denormal-fp-math"),
2604  StringLiteral("denormal-fp-math-f32"),
2605  StringLiteral("fp-contract"),
2606  StringLiteral("frame-pointer"),
2607  StringLiteral("instrument-function-entry"),
2608  StringLiteral("instrument-function-exit"),
2609  StringLiteral("memory"),
2610  StringLiteral("no-infs-fp-math"),
2611  StringLiteral("no-nans-fp-math"),
2612  StringLiteral("no-signed-zeros-fp-math"),
2613  StringLiteral("noinline"),
2614  StringLiteral("nounwind"),
2615  StringLiteral("optnone"),
2616  StringLiteral("target-features"),
2617  StringLiteral("tune-cpu"),
2618  StringLiteral("unsafe-fp-math"),
2619  StringLiteral("uwtable"),
2620  StringLiteral("vscale_range"),
2621  StringLiteral("willreturn"),
2622 };
2623 
2624 /// Converts LLVM attributes from `func` into MLIR attributes and adds them
2625 /// to `funcOp` as passthrough attributes, skipping those listed in
2626 /// `kExplicitLLVMFuncAttributes`.
2627 static void processPassthroughAttrs(llvm::Function *func, LLVMFuncOp funcOp) {
2628  llvm::AttributeSet funcAttrs = func->getAttributes().getAttributes(
2629  llvm::AttributeList::AttrIndex::FunctionIndex);
2630  ArrayAttr passthroughAttr =
2631  convertLLVMAttributesToMLIR(funcOp.getLoc(), funcOp.getContext(),
2632  funcAttrs, kExplicitLLVMFuncOpAttributes);
2633  if (!passthroughAttr.empty())
2634  funcOp.setPassthroughAttr(passthroughAttr);
2635 }
2636 
2638  LLVMFuncOp funcOp) {
2639  processMemoryEffects(func, funcOp);
2640  processPassthroughAttrs(func, funcOp);
2641 
2642  if (func->hasFnAttribute(llvm::Attribute::NoInline))
2643  funcOp.setNoInline(true);
2644  if (func->hasFnAttribute(llvm::Attribute::AlwaysInline))
2645  funcOp.setAlwaysInline(true);
2646  if (func->hasFnAttribute(llvm::Attribute::OptimizeNone))
2647  funcOp.setOptimizeNone(true);
2648  if (func->hasFnAttribute(llvm::Attribute::Convergent))
2649  funcOp.setConvergent(true);
2650  if (func->hasFnAttribute(llvm::Attribute::NoUnwind))
2651  funcOp.setNoUnwind(true);
2652  if (func->hasFnAttribute(llvm::Attribute::WillReturn))
2653  funcOp.setWillReturn(true);
2654 
2655  if (func->hasFnAttribute("aarch64_pstate_sm_enabled"))
2656  funcOp.setArmStreaming(true);
2657  else if (func->hasFnAttribute("aarch64_pstate_sm_body"))
2658  funcOp.setArmLocallyStreaming(true);
2659  else if (func->hasFnAttribute("aarch64_pstate_sm_compatible"))
2660  funcOp.setArmStreamingCompatible(true);
2661 
2662  if (func->hasFnAttribute("aarch64_new_za"))
2663  funcOp.setArmNewZa(true);
2664  else if (func->hasFnAttribute("aarch64_in_za"))
2665  funcOp.setArmInZa(true);
2666  else if (func->hasFnAttribute("aarch64_out_za"))
2667  funcOp.setArmOutZa(true);
2668  else if (func->hasFnAttribute("aarch64_inout_za"))
2669  funcOp.setArmInoutZa(true);
2670  else if (func->hasFnAttribute("aarch64_preserves_za"))
2671  funcOp.setArmPreservesZa(true);
2672 
2673  llvm::Attribute attr = func->getFnAttribute(llvm::Attribute::VScaleRange);
2674  if (attr.isValid()) {
2675  MLIRContext *context = funcOp.getContext();
2676  auto intTy = IntegerType::get(context, 32);
2677  funcOp.setVscaleRangeAttr(LLVM::VScaleRangeAttr::get(
2678  context, IntegerAttr::get(intTy, attr.getVScaleRangeMin()),
2679  IntegerAttr::get(intTy, attr.getVScaleRangeMax().value_or(0))));
2680  }
2681 
2682  // Process frame-pointer attribute.
2683  if (func->hasFnAttribute("frame-pointer")) {
2684  StringRef stringRefFramePointerKind =
2685  func->getFnAttribute("frame-pointer").getValueAsString();
2686  funcOp.setFramePointerAttr(LLVM::FramePointerKindAttr::get(
2687  funcOp.getContext(), LLVM::framePointerKind::symbolizeFramePointerKind(
2688  stringRefFramePointerKind)
2689  .value()));
2690  }
2691 
2692  if (llvm::Attribute attr = func->getFnAttribute("target-cpu");
2693  attr.isStringAttribute())
2694  funcOp.setTargetCpuAttr(StringAttr::get(context, attr.getValueAsString()));
2695 
2696  if (llvm::Attribute attr = func->getFnAttribute("tune-cpu");
2697  attr.isStringAttribute())
2698  funcOp.setTuneCpuAttr(StringAttr::get(context, attr.getValueAsString()));
2699 
2700  if (llvm::Attribute attr = func->getFnAttribute("target-features");
2701  attr.isStringAttribute())
2702  funcOp.setTargetFeaturesAttr(
2703  LLVM::TargetFeaturesAttr::get(context, attr.getValueAsString()));
2704 
2705  if (llvm::Attribute attr = func->getFnAttribute("reciprocal-estimates");
2706  attr.isStringAttribute())
2707  funcOp.setReciprocalEstimatesAttr(
2708  StringAttr::get(context, attr.getValueAsString()));
2709 
2710  if (llvm::Attribute attr = func->getFnAttribute("prefer-vector-width");
2711  attr.isStringAttribute())
2712  funcOp.setPreferVectorWidth(attr.getValueAsString());
2713 
2714  if (llvm::Attribute attr = func->getFnAttribute("unsafe-fp-math");
2715  attr.isStringAttribute())
2716  funcOp.setUnsafeFpMath(attr.getValueAsBool());
2717 
2718  if (llvm::Attribute attr = func->getFnAttribute("no-infs-fp-math");
2719  attr.isStringAttribute())
2720  funcOp.setNoInfsFpMath(attr.getValueAsBool());
2721 
2722  if (llvm::Attribute attr = func->getFnAttribute("no-nans-fp-math");
2723  attr.isStringAttribute())
2724  funcOp.setNoNansFpMath(attr.getValueAsBool());
2725 
2726  if (llvm::Attribute attr = func->getFnAttribute("instrument-function-entry");
2727  attr.isStringAttribute())
2728  funcOp.setInstrumentFunctionEntry(
2729  StringAttr::get(context, attr.getValueAsString()));
2730 
2731  if (llvm::Attribute attr = func->getFnAttribute("instrument-function-exit");
2732  attr.isStringAttribute())
2733  funcOp.setInstrumentFunctionExit(
2734  StringAttr::get(context, attr.getValueAsString()));
2735 
2736  if (llvm::Attribute attr = func->getFnAttribute("no-signed-zeros-fp-math");
2737  attr.isStringAttribute())
2738  funcOp.setNoSignedZerosFpMath(attr.getValueAsBool());
2739 
2740  if (llvm::Attribute attr = func->getFnAttribute("denormal-fp-math");
2741  attr.isStringAttribute())
2742  funcOp.setDenormalFpMathAttr(
2743  StringAttr::get(context, attr.getValueAsString()));
2744 
2745  if (llvm::Attribute attr = func->getFnAttribute("denormal-fp-math-f32");
2746  attr.isStringAttribute())
2747  funcOp.setDenormalFpMathF32Attr(
2748  StringAttr::get(context, attr.getValueAsString()));
2749 
2750  if (llvm::Attribute attr = func->getFnAttribute("fp-contract");
2751  attr.isStringAttribute())
2752  funcOp.setFpContractAttr(StringAttr::get(context, attr.getValueAsString()));
2753 
2754  if (func->hasUWTable()) {
2755  ::llvm::UWTableKind uwtableKind = func->getUWTableKind();
2756  funcOp.setUwtableKindAttr(LLVM::UWTableKindAttr::get(
2757  funcOp.getContext(), convertUWTableKindFromLLVM(uwtableKind)));
2758  }
2759 }
2760 
2761 DictionaryAttr
2762 ModuleImport::convertArgOrResultAttrSet(llvm::AttributeSet llvmAttrSet) {
2763  SmallVector<NamedAttribute> paramAttrs;
2764  for (auto [llvmKind, mlirName] : getAttrKindToNameMapping()) {
2765  auto llvmAttr = llvmAttrSet.getAttribute(llvmKind);
2766  // Skip attributes that are not attached.
2767  if (!llvmAttr.isValid())
2768  continue;
2769 
2770  // TODO: Import captures(none) as a nocapture unit attribute until the
2771  // LLVM dialect switches to the captures representation.
2772  if (llvmAttr.hasKindAsEnum() &&
2773  llvmAttr.getKindAsEnum() == llvm::Attribute::Captures) {
2774  if (llvm::capturesNothing(llvmAttr.getCaptureInfo()))
2775  paramAttrs.push_back(
2776  builder.getNamedAttr(mlirName, builder.getUnitAttr()));
2777  continue;
2778  }
2779 
2780  Attribute mlirAttr;
2781  if (llvmAttr.isTypeAttribute())
2782  mlirAttr = TypeAttr::get(convertType(llvmAttr.getValueAsType()));
2783  else if (llvmAttr.isIntAttribute())
2784  mlirAttr = builder.getI64IntegerAttr(llvmAttr.getValueAsInt());
2785  else if (llvmAttr.isEnumAttribute())
2786  mlirAttr = builder.getUnitAttr();
2787  else if (llvmAttr.isConstantRangeAttribute()) {
2788  const llvm::ConstantRange &value = llvmAttr.getValueAsConstantRange();
2789  mlirAttr = builder.getAttr<LLVM::ConstantRangeAttr>(value.getLower(),
2790  value.getUpper());
2791  } else {
2792  llvm_unreachable("unexpected parameter attribute kind");
2793  }
2794  paramAttrs.push_back(builder.getNamedAttr(mlirName, mlirAttr));
2795  }
2796 
2797  return builder.getDictionaryAttr(paramAttrs);
2798 }
2799 
2800 void ModuleImport::convertArgAndResultAttrs(llvm::Function *func,
2801  LLVMFuncOp funcOp) {
2802  auto llvmAttrs = func->getAttributes();
2803  for (size_t i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
2804  llvm::AttributeSet llvmArgAttrs = llvmAttrs.getParamAttrs(i);
2805  funcOp.setArgAttrs(i, convertArgOrResultAttrSet(llvmArgAttrs));
2806  }
2807  // Convert the result attributes and attach them wrapped in an ArrayAttribute
2808  // to the funcOp.
2809  llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
2810  if (!llvmResAttr.hasAttributes())
2811  return;
2812  funcOp.setResAttrsAttr(
2813  builder.getArrayAttr({convertArgOrResultAttrSet(llvmResAttr)}));
2814 }
2815 
2817  llvm::CallBase *call, ArgAndResultAttrsOpInterface attrsOp,
2818  ArrayRef<unsigned> immArgPositions) {
2819  // Compute the set of immediate argument positions.
2820  llvm::SmallDenseSet<unsigned> immArgPositionsSet(immArgPositions.begin(),
2821  immArgPositions.end());
2822  // Convert the argument attributes and filter out immediate arguments.
2823  llvm::AttributeList llvmAttrs = call->getAttributes();
2824  SmallVector<llvm::AttributeSet> llvmArgAttrsSet;
2825  bool anyArgAttrs = false;
2826  for (size_t i = 0, e = call->arg_size(); i < e; ++i) {
2827  // Skip immediate arguments.
2828  if (immArgPositionsSet.contains(i))
2829  continue;
2830  llvmArgAttrsSet.emplace_back(llvmAttrs.getParamAttrs(i));
2831  if (llvmArgAttrsSet.back().hasAttributes())
2832  anyArgAttrs = true;
2833  }
2834  auto getArrayAttr = [&](ArrayRef<DictionaryAttr> dictAttrs) {
2835  SmallVector<Attribute> attrs;
2836  for (auto &dict : dictAttrs)
2837  attrs.push_back(dict ? dict : builder.getDictionaryAttr({}));
2838  return builder.getArrayAttr(attrs);
2839  };
2840  if (anyArgAttrs) {
2841  SmallVector<DictionaryAttr> argAttrs;
2842  for (auto &llvmArgAttrs : llvmArgAttrsSet)
2843  argAttrs.emplace_back(convertArgOrResultAttrSet(llvmArgAttrs));
2844  attrsOp.setArgAttrsAttr(getArrayAttr(argAttrs));
2845  }
2846 
2847  // Convert the result attributes.
2848  llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
2849  if (!llvmResAttr.hasAttributes())
2850  return;
2851  DictionaryAttr resAttrs = convertArgOrResultAttrSet(llvmResAttr);
2852  attrsOp.setResAttrsAttr(getArrayAttr({resAttrs}));
2853 }
2854 
2855 template <typename Op>
2856 static LogicalResult convertCallBaseAttributes(llvm::CallBase *inst, Op op) {
2857  op.setCConv(convertCConvFromLLVM(inst->getCallingConv()));
2858  return success();
2859 }
2860 
2861 LogicalResult ModuleImport::convertInvokeAttributes(llvm::InvokeInst *inst,
2862  InvokeOp op) {
2863  return convertCallBaseAttributes(inst, op);
2864 }
2865 
2866 LogicalResult ModuleImport::convertCallAttributes(llvm::CallInst *inst,
2867  CallOp op) {
2868  setFastmathFlagsAttr(inst, op.getOperation());
2869  // Query the attributes directly instead of using `inst->getFnAttr(Kind)`, the
2870  // latter does additional lookup to the parent and inherits, changing the
2871  // semantics too early.
2872  llvm::AttributeList callAttrs = inst->getAttributes();
2873 
2874  op.setTailCallKind(convertTailCallKindFromLLVM(inst->getTailCallKind()));
2875  op.setConvergent(callAttrs.getFnAttr(llvm::Attribute::Convergent).isValid());
2876  op.setNoUnwind(callAttrs.getFnAttr(llvm::Attribute::NoUnwind).isValid());
2877  op.setWillReturn(callAttrs.getFnAttr(llvm::Attribute::WillReturn).isValid());
2878  op.setNoInline(callAttrs.getFnAttr(llvm::Attribute::NoInline).isValid());
2879  op.setAlwaysInline(
2880  callAttrs.getFnAttr(llvm::Attribute::AlwaysInline).isValid());
2881  op.setInlineHint(callAttrs.getFnAttr(llvm::Attribute::InlineHint).isValid());
2882 
2883  llvm::MemoryEffects memEffects = inst->getMemoryEffects();
2884  ModRefInfo othermem = convertModRefInfoFromLLVM(
2885  memEffects.getModRef(llvm::MemoryEffects::Location::Other));
2886  ModRefInfo argMem = convertModRefInfoFromLLVM(
2887  memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
2888  ModRefInfo inaccessibleMem = convertModRefInfoFromLLVM(
2889  memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
2890  auto memAttr = MemoryEffectsAttr::get(op.getContext(), othermem, argMem,
2891  inaccessibleMem);
2892  // Only set the attribute when it does not match the default value.
2893  if (!memAttr.isReadWrite())
2894  op.setMemoryEffectsAttr(memAttr);
2895 
2896  return convertCallBaseAttributes(inst, op);
2897 }
2898 
2899 LogicalResult ModuleImport::processFunction(llvm::Function *func) {
2900  clearRegionState();
2901 
2902  auto functionType =
2903  dyn_cast<LLVMFunctionType>(convertType(func->getFunctionType()));
2904  if (func->isIntrinsic() &&
2905  iface.isConvertibleIntrinsic(func->getIntrinsicID()))
2906  return success();
2907 
2908  bool dsoLocal = func->isDSOLocal();
2909  CConv cconv = convertCConvFromLLVM(func->getCallingConv());
2910 
2911  // Insert the function at the end of the module.
2912  OpBuilder::InsertionGuard guard(builder);
2913  builder.setInsertionPointToEnd(mlirModule.getBody());
2914 
2915  Location loc = debugImporter->translateFuncLocation(func);
2916  LLVMFuncOp funcOp = LLVMFuncOp::create(
2917  builder, loc, func->getName(), functionType,
2918  convertLinkageFromLLVM(func->getLinkage()), dsoLocal, cconv);
2919 
2920  convertArgAndResultAttrs(func, funcOp);
2921 
2922  if (FlatSymbolRefAttr personality = getPersonalityAsAttr(func))
2923  funcOp.setPersonalityAttr(personality);
2924  else if (func->hasPersonalityFn())
2925  emitWarning(funcOp.getLoc(), "could not deduce personality, skipping it");
2926 
2927  if (func->hasGC())
2928  funcOp.setGarbageCollector(StringRef(func->getGC()));
2929 
2930  if (func->hasAtLeastLocalUnnamedAddr())
2931  funcOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(func->getUnnamedAddr()));
2932 
2933  if (func->hasSection())
2934  funcOp.setSection(StringRef(func->getSection()));
2935 
2936  funcOp.setVisibility_(convertVisibilityFromLLVM(func->getVisibility()));
2937 
2938  if (func->hasComdat())
2939  funcOp.setComdatAttr(comdatMapping.lookup(func->getComdat()));
2940 
2941  if (llvm::MaybeAlign maybeAlign = func->getAlign())
2942  funcOp.setAlignment(maybeAlign->value());
2943 
2944  // Handle Function attributes.
2945  processFunctionAttributes(func, funcOp);
2946 
2947  // Convert non-debug metadata by using the dialect interface.
2949  func->getAllMetadata(allMetadata);
2950  for (auto &[kind, node] : allMetadata) {
2951  if (!iface.isConvertibleMetadata(kind))
2952  continue;
2953  if (failed(iface.setMetadataAttrs(builder, kind, node, funcOp, *this))) {
2954  emitWarning(funcOp.getLoc())
2955  << "unhandled function metadata: " << diagMD(node, llvmModule.get())
2956  << " on " << diag(*func);
2957  }
2958  }
2959 
2960  if (func->isDeclaration())
2961  return success();
2962 
2963  // Collect the set of basic blocks reachable from the function's entry block.
2964  // This step is crucial as LLVM IR can contain unreachable blocks that
2965  // self-dominate. As a result, an operation might utilize a variable it
2966  // defines, which the import does not support. Given that MLIR lacks block
2967  // label support, we can safely remove unreachable blocks, as there are no
2968  // indirect branch instructions that could potentially target these blocks.
2969  llvm::df_iterator_default_set<llvm::BasicBlock *> reachable;
2970  for (llvm::BasicBlock *basicBlock : llvm::depth_first_ext(func, reachable))
2971  (void)basicBlock;
2972 
2973  // Eagerly create all reachable blocks.
2974  SmallVector<llvm::BasicBlock *> reachableBasicBlocks;
2975  for (llvm::BasicBlock &basicBlock : *func) {
2976  // Skip unreachable blocks.
2977  if (!reachable.contains(&basicBlock)) {
2978  if (basicBlock.hasAddressTaken())
2979  return emitError(funcOp.getLoc())
2980  << "unreachable block '" << basicBlock.getName()
2981  << "' with address taken";
2982  continue;
2983  }
2984  Region &body = funcOp.getBody();
2985  Block *block = builder.createBlock(&body, body.end());
2986  mapBlock(&basicBlock, block);
2987  reachableBasicBlocks.push_back(&basicBlock);
2988  }
2989 
2990  // Add function arguments to the entry block.
2991  for (const auto &it : llvm::enumerate(func->args())) {
2992  BlockArgument blockArg = funcOp.getFunctionBody().addArgument(
2993  functionType.getParamType(it.index()), funcOp.getLoc());
2994  mapValue(&it.value(), blockArg);
2995  }
2996 
2997  // Process the blocks in topological order. The ordered traversal ensures
2998  // operands defined in a dominating block have a valid mapping to an MLIR
2999  // value once a block is translated.
3001  getTopologicallySortedBlocks(reachableBasicBlocks);
3002  setConstantInsertionPointToStart(lookupBlock(blocks.front()));
3003  for (llvm::BasicBlock *basicBlock : blocks)
3004  if (failed(processBasicBlock(basicBlock, lookupBlock(basicBlock))))
3005  return failure();
3006 
3007  // Process the debug intrinsics that require a delayed conversion after
3008  // everything else was converted.
3009  if (failed(processDebugIntrinsics()))
3010  return failure();
3011 
3012  return success();
3013 }
3014 
3015 /// Checks if `dbgIntr` is a kill location that holds metadata instead of an SSA
3016 /// value.
3017 static bool isMetadataKillLocation(llvm::DbgVariableIntrinsic *dbgIntr) {
3018  if (!dbgIntr->isKillLocation())
3019  return false;
3020  llvm::Value *value = dbgIntr->getArgOperand(0);
3021  auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
3022  if (!nodeAsVal)
3023  return false;
3024  return !isa<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
3025 }
3026 
3027 LogicalResult
3028 ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr,
3029  DominanceInfo &domInfo) {
3030  Location loc = translateLoc(dbgIntr->getDebugLoc());
3031  auto emitUnsupportedWarning = [&]() {
3032  if (emitExpensiveWarnings)
3033  emitWarning(loc) << "dropped intrinsic: " << diag(*dbgIntr);
3034  return success();
3035  };
3036  // Drop debug intrinsics with arg lists.
3037  // TODO: Support debug intrinsics that have arg lists.
3038  if (dbgIntr->hasArgList())
3039  return emitUnsupportedWarning();
3040  // Kill locations can have metadata nodes as location operand. This
3041  // cannot be converted to poison as the type cannot be reconstructed.
3042  // TODO: find a way to support this case.
3043  if (isMetadataKillLocation(dbgIntr))
3044  return emitUnsupportedWarning();
3045  // Drop debug intrinsics if the associated variable information cannot be
3046  // translated due to cyclic debug metadata.
3047  // TODO: Support cyclic debug metadata.
3048  DILocalVariableAttr localVariableAttr =
3049  matchLocalVariableAttr(dbgIntr->getArgOperand(1));
3050  if (!localVariableAttr)
3051  return emitUnsupportedWarning();
3052  FailureOr<Value> argOperand = convertMetadataValue(dbgIntr->getArgOperand(0));
3053  if (failed(argOperand))
3054  return emitError(loc) << "failed to convert a debug intrinsic operand: "
3055  << diag(*dbgIntr);
3056 
3057  // Ensure that the debug intrinsic is inserted right after its operand is
3058  // defined. Otherwise, the operand might not necessarily dominate the
3059  // intrinsic. If the defining operation is a terminator, insert the intrinsic
3060  // into a dominated block.
3061  OpBuilder::InsertionGuard guard(builder);
3062  if (Operation *op = argOperand->getDefiningOp();
3063  op && op->hasTrait<OpTrait::IsTerminator>()) {
3064  // Find a dominated block that can hold the debug intrinsic.
3065  auto dominatedBlocks = domInfo.getNode(op->getBlock())->children();
3066  // If no block is dominated by the terminator, this intrinisc cannot be
3067  // converted.
3068  if (dominatedBlocks.empty())
3069  return emitUnsupportedWarning();
3070  // Set insertion point before the terminator, to avoid inserting something
3071  // before landingpads.
3072  Block *dominatedBlock = (*dominatedBlocks.begin())->getBlock();
3073  builder.setInsertionPoint(dominatedBlock->getTerminator());
3074  } else {
3075  Value insertPt = *argOperand;
3076  if (auto blockArg = dyn_cast<BlockArgument>(*argOperand)) {
3077  // The value might be coming from a phi node and is now a block argument,
3078  // which means the insertion point is set to the start of the block. If
3079  // this block is a target destination of an invoke, the insertion point
3080  // must happen after the landing pad operation.
3081  Block *insertionBlock = argOperand->getParentBlock();
3082  if (!insertionBlock->empty() &&
3083  isa<LandingpadOp>(insertionBlock->front()))
3084  insertPt = cast<LandingpadOp>(insertionBlock->front()).getRes();
3085  }
3086 
3087  builder.setInsertionPointAfterValue(insertPt);
3088  }
3089  auto locationExprAttr =
3090  debugImporter->translateExpression(dbgIntr->getExpression());
3091  Operation *op =
3093  .Case([&](llvm::DbgDeclareInst *) {
3094  return LLVM::DbgDeclareOp::create(
3095  builder, loc, *argOperand, localVariableAttr, locationExprAttr);
3096  })
3097  .Case([&](llvm::DbgValueInst *) {
3098  return LLVM::DbgValueOp::create(
3099  builder, loc, *argOperand, localVariableAttr, locationExprAttr);
3100  });
3101  mapNoResultOp(dbgIntr, op);
3102  setNonDebugMetadataAttrs(dbgIntr, op);
3103  return success();
3104 }
3105 
3106 LogicalResult ModuleImport::processDebugIntrinsics() {
3107  DominanceInfo domInfo;
3108  for (llvm::Instruction *inst : debugIntrinsics) {
3109  auto *intrCall = cast<llvm::DbgVariableIntrinsic>(inst);
3110  if (failed(processDebugIntrinsic(intrCall, domInfo)))
3111  return failure();
3112  }
3113  return success();
3114 }
3115 
3116 LogicalResult ModuleImport::processBasicBlock(llvm::BasicBlock *bb,
3117  Block *block) {
3118  builder.setInsertionPointToStart(block);
3119  for (llvm::Instruction &inst : *bb) {
3120  if (failed(processInstruction(&inst)))
3121  return failure();
3122 
3123  // Skip additional processing when the instructions is a debug intrinsics
3124  // that was not yet converted.
3125  if (debugIntrinsics.contains(&inst))
3126  continue;
3127 
3128  // Set the non-debug metadata attributes on the imported operation and emit
3129  // a warning if an instruction other than a phi instruction is dropped
3130  // during the import.
3131  if (Operation *op = lookupOperation(&inst)) {
3132  setNonDebugMetadataAttrs(&inst, op);
3133  } else if (inst.getOpcode() != llvm::Instruction::PHI) {
3134  if (emitExpensiveWarnings) {
3135  Location loc = debugImporter->translateLoc(inst.getDebugLoc());
3136  emitWarning(loc) << "dropped instruction: " << diag(inst);
3137  }
3138  }
3139  }
3140 
3141  if (bb->hasAddressTaken()) {
3142  OpBuilder::InsertionGuard guard(builder);
3143  builder.setInsertionPointToStart(block);
3144  BlockTagOp::create(builder, block->getParentOp()->getLoc(),
3145  BlockTagAttr::get(context, bb->getNumber()));
3146  }
3147  return success();
3148 }
3149 
3150 FailureOr<SmallVector<AccessGroupAttr>>
3151 ModuleImport::lookupAccessGroupAttrs(const llvm::MDNode *node) const {
3152  return loopAnnotationImporter->lookupAccessGroupAttrs(node);
3153 }
3154 
3155 LoopAnnotationAttr
3157  Location loc) const {
3158  return loopAnnotationImporter->translateLoopAnnotation(node, loc);
3159 }
3160 
3161 FailureOr<DereferenceableAttr>
3163  unsigned kindID) {
3164  Location loc = mlirModule.getLoc();
3165 
3166  // The only operand should be a constant integer representing the number of
3167  // dereferenceable bytes.
3168  if (node->getNumOperands() != 1)
3169  return emitError(loc) << "dereferenceable metadata must have one operand: "
3170  << diagMD(node, llvmModule.get());
3171 
3172  auto *numBytesMD = dyn_cast<llvm::ConstantAsMetadata>(node->getOperand(0));
3173  auto *numBytesCst = dyn_cast<llvm::ConstantInt>(numBytesMD->getValue());
3174  if (!numBytesCst || !numBytesCst->getValue().isNonNegative())
3175  return emitError(loc) << "dereferenceable metadata operand must be a "
3176  "non-negative constant integer: "
3177  << diagMD(node, llvmModule.get());
3178 
3179  bool mayBeNull = kindID == llvm::LLVMContext::MD_dereferenceable_or_null;
3180  auto derefAttr = builder.getAttr<DereferenceableAttr>(
3181  numBytesCst->getZExtValue(), mayBeNull);
3182 
3183  return derefAttr;
3184 }
3185 
3187  std::unique_ptr<llvm::Module> llvmModule, MLIRContext *context,
3188  bool emitExpensiveWarnings, bool dropDICompositeTypeElements,
3189  bool loadAllDialects, bool preferUnregisteredIntrinsics,
3190  bool importStructsAsLiterals) {
3191  // Preload all registered dialects to allow the import to iterate the
3192  // registered LLVMImportDialectInterface implementations and query the
3193  // supported LLVM IR constructs before starting the translation. Assumes the
3194  // LLVM and DLTI dialects that convert the core LLVM IR constructs have been
3195  // registered before.
3196  assert(llvm::is_contained(context->getAvailableDialects(),
3197  LLVMDialect::getDialectNamespace()));
3198  assert(llvm::is_contained(context->getAvailableDialects(),
3199  DLTIDialect::getDialectNamespace()));
3200  if (loadAllDialects)
3201  context->loadAllAvailableDialects();
3202  OwningOpRef<ModuleOp> module(ModuleOp::create(FileLineColLoc::get(
3203  StringAttr::get(context, llvmModule->getSourceFileName()), /*line=*/0,
3204  /*column=*/0)));
3205 
3206  ModuleImport moduleImport(module.get(), std::move(llvmModule),
3207  emitExpensiveWarnings, dropDICompositeTypeElements,
3208  preferUnregisteredIntrinsics,
3209  importStructsAsLiterals);
3210  if (failed(moduleImport.initializeImportInterface()))
3211  return {};
3212  if (failed(moduleImport.convertDataLayout()))
3213  return {};
3214  if (failed(moduleImport.convertComdats()))
3215  return {};
3216  if (failed(moduleImport.convertMetadata()))
3217  return {};
3218  if (failed(moduleImport.convertGlobals()))
3219  return {};
3220  if (failed(moduleImport.convertFunctions()))
3221  return {};
3222  if (failed(moduleImport.convertAliases()))
3223  return {};
3224  if (failed(moduleImport.convertIFuncs()))
3225  return {};
3226  moduleImport.convertTargetTriple();
3227  moduleImport.convertModuleLevelAsm();
3228  return module;
3229 }
static MLIRContext * getContext(OpFoldResult val)
union mlir::linalg::@1241::ArityGroupAndKind::Kind kind
static SmallVector< int64_t > getPositionFromIndices(ArrayRef< unsigned > indices)
Converts an array of unsigned indices to a signed integer position array.
static StringRef getLLVMSyncScope(llvm::Instruction *inst)
Converts the sync scope identifier of inst to the string representation necessary to build an atomic ...
static std::string diag(const llvm::Value &value)
static void processPassthroughAttrs(llvm::Function *func, LLVMFuncOp funcOp)
Converts LLVM attributes from func into MLIR attributes and adds them to funcOp as passthrough attrib...
static LogicalResult convertCallBaseAttributes(llvm::CallBase *inst, Op op)
static void processMemoryEffects(llvm::Function *func, LLVMFuncOp funcOp)
static Attribute convertCGProfileModuleFlagValue(ModuleOp mlirModule, llvm::MDTuple *mdTuple)
static constexpr StringRef getGlobalDtorsVarName()
Returns the name of the global_dtors global variables.
static llvm::ConstantAsMetadata * getConstantMDFromKeyValueTuple(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &md, StringRef matchKey, bool optional=false)
Extract a constant metadata value from a two element tuple (<key, value>).
static Type getVectorTypeForAttr(Type type, ArrayRef< int64_t > arrayShape={})
Returns type if it is a builtin integer or floating-point vector type that can be used to create an a...
static LogicalResult convertInstructionImpl(OpBuilder &odsBuilder, llvm::Instruction *inst, ModuleImport &moduleImport, LLVMImportInterface &iface)
Converts the LLVM instructions that have a generated MLIR builder.
static constexpr StringRef getNamelessGlobalPrefix()
Prefix used for symbols of nameless llvm globals.
static Attribute convertModuleFlagValueFromMDTuple(ModuleOp mlirModule, const llvm::Module *llvmModule, StringRef key, llvm::MDTuple *mdTuple)
Invoke specific handlers for each known module flag value, returns nullptr if the key is unknown or u...
static constexpr std::array kExplicitLLVMFuncOpAttributes
static constexpr StringRef getGlobalComdatOpName()
Returns the symbol name for the module-level comdat operation.
static LogicalResult checkFunctionTypeCompatibility(LLVMFunctionType callType, LLVMFunctionType calleeType)
Checks if callType and calleeType are compatible and can be represented in MLIR.
static constexpr StringRef getGlobalCtorsVarName()
Returns the name of the global_ctors global variables.
static void processTargetSpecificAttrs(llvm::GlobalVariable *globalVar, GlobalOp globalOp)
Converts LLVM attributes from globalVar into MLIR attributes and adds them to globalOp as target-spec...
static Attribute convertProfileSummaryModuleFlagValue(ModuleOp mlirModule, const llvm::Module *llvmModule, llvm::MDTuple *mdTuple)
static std::optional< ProfileSummaryFormatKind > convertProfileSummaryFormat(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &formatMD)
static bool isMetadataKillLocation(llvm::DbgVariableIntrinsic *dbgIntr)
Checks if dbgIntr is a kill location that holds metadata instead of an SSA value.
static llvm::MDTuple * getTwoElementMDTuple(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &md)
Extract a two element MDTuple from a MDOperand.
static TypedAttr getScalarConstantAsAttr(OpBuilder &builder, llvm::Constant *constScalar)
Returns an integer or float attribute for the provided scalar constant constScalar or nullptr if the ...
static SetVector< llvm::BasicBlock * > getTopologicallySortedBlocks(ArrayRef< llvm::BasicBlock * > basicBlocks)
Get a topologically sorted list of blocks for the given basic blocks.
static std::string diagMD(const llvm::Metadata *node, const llvm::Module *module)
static FailureOr< SmallVector< ModuleFlagProfileSummaryDetailedAttr > > convertProfileSummaryDetailed(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &summaryMD)
static FailureOr< uint64_t > convertInt64FromKeyValueTuple(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &md, StringRef matchKey)
Extract an integer value from a two element tuple (<key, value>).
static SmallVector< Attribute > getSequenceConstantAsAttrs(OpBuilder &builder, llvm::ConstantDataSequential *constSequence)
Returns an integer or float attribute array for the provided constant sequence constSequence or nullp...
static ArrayAttr convertLLVMAttributesToMLIR(Location loc, MLIRContext *context, llvm::AttributeSet attributes, ArrayRef< StringLiteral > attributesToSkip={})
Converts LLVM string, integer, and enum attributes into MLIR attributes, skipping those in attributes...
static llvm::ManagedStatic< PassManagerOptions > options
static void contract(RootOrderingGraph &graph, ArrayRef< Value > cycle, const DenseMap< Value, unsigned > &parentDepths, DenseMap< Value, Value > &actualSource, DenseMap< Value, Value > &actualTarget)
Contracts the specified cycle in the given graph in-place.
Attributes are known-constant values of operations.
Definition: Attributes.h:25
This class represents an argument of a Block.
Definition: Value.h:309
Block represents an ordered list of Operations.
Definition: Block.h:33
bool empty()
Definition: Block.h:148
Operation * getTerminator()
Get the terminator operation of this block.
Definition: Block.cpp:244
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
Definition: Block.cpp:153
Operation & front()
Definition: Block.h:153
Operation * getParentOp()
Returns the closest surrounding operation that contains this block.
Definition: Block.cpp:31
UnitAttr getUnitAttr()
Definition: Builders.cpp:97
IntegerAttr getI32IntegerAttr(int32_t value)
Definition: Builders.cpp:199
IntegerAttr getIntegerAttr(Type type, int64_t value)
Definition: Builders.cpp:227
ArrayAttr getI32ArrayAttr(ArrayRef< int32_t > values)
Definition: Builders.cpp:275
FloatAttr getFloatAttr(Type type, double value)
Definition: Builders.cpp:253
IntegerType getI32Type()
Definition: Builders.cpp:62
IntegerAttr getI64IntegerAttr(int64_t value)
Definition: Builders.cpp:111
StringAttr getStringAttr(const Twine &bytes)
Definition: Builders.cpp:261
TypedAttr getZeroAttr(Type type)
Definition: Builders.cpp:323
MLIRContext * getContext() const
Definition: Builders.h:56
ArrayAttr getArrayAttr(ArrayRef< Attribute > value)
Definition: Builders.cpp:265
DictionaryAttr getDictionaryAttr(ArrayRef< NamedAttribute > value)
Definition: Builders.cpp:103
NamedAttribute getNamedAttr(StringRef name, Attribute val)
Definition: Builders.cpp:93
ArrayAttr getStrArrayAttr(ArrayRef< StringRef > values)
Definition: Builders.cpp:305
Attr getAttr(Args &&...args)
Get or construct an instance of the attribute Attr with provided arguments.
Definition: Builders.h:98
static DenseElementsAttr get(ShapedType type, ArrayRef< Attribute > values)
Constructs a dense elements attribute from an array of element values.
static DistinctAttr create(Attribute referencedAttr)
Creates a distinct attribute that associates a referenced attribute with a unique identifier.
A class for computing basic dominance information.
Definition: Dominance.h:140
static FileLineColLoc get(StringAttr filename, unsigned line, unsigned column)
Definition: Location.cpp:157
A symbol reference with a reference path containing a single element.
static FlatSymbolRefAttr get(StringAttr value)
Construct a symbol reference for the given value name.
StringRef getValue() const
Returns the name of the held symbol reference.
Interface collection for the import of LLVM IR that dispatches to a concrete dialect interface implem...
LogicalResult convertInstruction(OpBuilder &builder, llvm::Instruction *inst, ArrayRef< llvm::Value * > llvmOperands, LLVM::ModuleImport &moduleImport) const
Converts the LLVM instruction to an MLIR operation if a conversion exists.
LogicalResult convertIntrinsic(OpBuilder &builder, llvm::CallInst *inst, LLVM::ModuleImport &moduleImport) const
Converts the LLVM intrinsic to an MLIR operation if a conversion exists.
LogicalResult setMetadataAttrs(OpBuilder &builder, unsigned kind, llvm::MDNode *node, Operation *op, LLVM::ModuleImport &moduleImport) const
Attaches the given LLVM metadata to the imported operation if a conversion to one or more MLIR dialec...
bool isConvertibleMetadata(unsigned kind)
Returns true if the given LLVM IR metadata is convertible to an MLIR attribute.
bool isConvertibleInstruction(unsigned id)
Returns true if the given LLVM IR instruction is convertible to an MLIR operation.
bool isConvertibleIntrinsic(llvm::Intrinsic::ID id)
Returns true if the given LLVM IR intrinsic is convertible to an MLIR operation.
Module import implementation class that provides methods to import globals and functions from an LLVM...
Definition: ModuleImport.h:48
LogicalResult convertIFuncs()
Converts all ifuncs of the LLVM module to MLIR variables.
LogicalResult convertIntrinsicArguments(ArrayRef< llvm::Value * > values, ArrayRef< llvm::OperandBundleUse > opBundles, bool requiresOpBundles, ArrayRef< unsigned > immArgPositions, ArrayRef< StringLiteral > immArgAttrNames, SmallVectorImpl< Value > &valuesOut, SmallVectorImpl< NamedAttribute > &attrsOut)
Converts the LLVM values for an intrinsic to mixed MLIR values and attributes for LLVM_IntrOpBase.
Location translateLoc(llvm::DILocation *loc)
Translates the debug location.
LogicalResult convertComdats()
Converts all comdat selectors of the LLVM module to MLIR comdat operations.
LogicalResult convertAliases()
Converts all aliases of the LLVM module to MLIR variables.
LogicalResult convertFunctions()
Converts all functions of the LLVM module to MLIR functions.
FailureOr< SmallVector< Value > > convertValues(ArrayRef< llvm::Value * > values)
Converts a range of LLVM values to a range of MLIR values using the convertValue method,...
DILocalVariableAttr matchLocalVariableAttr(llvm::Value *value)
Converts value to a local variable attribute.
LogicalResult convertLinkerOptionsMetadata()
Converts !llvm.linker.options metadata to the llvm.linker.options LLVM dialect operation.
void mapBlock(llvm::BasicBlock *llvm, Block *mlir)
Stores the mapping between an LLVM block and its MLIR counterpart.
Definition: ModuleImport.h:135
void processFunctionAttributes(llvm::Function *func, LLVMFuncOp funcOp)
Converts function attributes of LLVM Function func into LLVM dialect attributes of LLVMFuncOp funcOp.
LogicalResult convertMetadata()
Converts all LLVM metadata nodes that translate to attributes such as alias analysis or access group ...
FailureOr< Value > convertValue(llvm::Value *value)
Converts an LLVM value to an MLIR value, or returns failure if the conversion fails.
LogicalResult initializeImportInterface()
Calls the LLVMImportInterface initialization that queries the registered dialect interfaces for the s...
Definition: ModuleImport.h:58
void addDebugIntrinsic(llvm::CallInst *intrinsic)
Adds a debug intrinsics to the list of intrinsics that should be converted after the function convers...
LogicalResult convertIdentMetadata()
Converts !llvm.ident metadata to the llvm.ident LLVM ModuleOp attribute.
Block * lookupBlock(llvm::BasicBlock *block) const
Returns the MLIR block mapped to the given LLVM block.
Definition: ModuleImport.h:142
FailureOr< Value > convertMetadataValue(llvm::Value *value)
Converts an LLVM metadata value to an MLIR value, or returns failure if the conversion fails.
FailureOr< SmallVector< AliasScopeAttr > > lookupAliasScopeAttrs(const llvm::MDNode *node) const
Returns the alias scope attributes that map to the alias scope nodes starting from the metadata node.
void setDisjointFlag(llvm::Instruction *inst, Operation *op) const
Sets the disjoint flag attribute for the imported operation op given the original instruction inst.
void mapNoResultOp(llvm::Instruction *llvm, Operation *mlir)
Stores a mapping between an LLVM instruction and the imported MLIR operation if the operation returns...
Definition: ModuleImport.h:108
void convertModuleLevelAsm()
Converts the module level asm of the LLVM module to an MLIR module level asm specification.
void setExactFlag(llvm::Instruction *inst, Operation *op) const
Sets the exact flag attribute for the imported operation op given the original instruction inst.
Type convertType(llvm::Type *type)
Converts the type from LLVM to MLIR LLVM dialect.
Definition: ModuleImport.h:190
Operation * lookupOperation(llvm::Instruction *inst)
Returns the MLIR operation mapped to the given LLVM instruction.
Definition: ModuleImport.h:128
ModuleImport(ModuleOp mlirModule, std::unique_ptr< llvm::Module > llvmModule, bool emitExpensiveWarnings, bool importEmptyDICompositeTypes, bool preferUnregisteredIntrinsics, bool importStructsAsLiterals)
DILabelAttr matchLabelAttr(llvm::Value *value)
Converts value to a label attribute. Asserts if the matching fails.
FloatAttr matchFloatAttr(llvm::Value *value)
Converts value to a float attribute. Asserts if the matching fails.
LoopAnnotationAttr translateLoopAnnotationAttr(const llvm::MDNode *node, Location loc) const
Returns the loop annotation attribute that corresponds to the given LLVM loop metadata node.
void setFastmathFlagsAttr(llvm::Instruction *inst, Operation *op) const
Sets the fastmath flags attribute for the imported operation op given the original instruction inst.
FailureOr< SmallVector< AliasScopeAttr > > matchAliasScopeAttrs(llvm::Value *value)
Converts value to an array of alias scopes or returns failure if the conversion fails.
Value lookupValue(llvm::Value *value)
Returns the MLIR value mapped to the given LLVM value.
Definition: ModuleImport.h:103
LogicalResult processFunction(llvm::Function *func)
Imports func into the current module.
LogicalResult convertDependentLibrariesMetadata()
Converts !llvm.dependent-libraries metadata to llvm.dependent_libraries LLVM ModuleOp attribute.
RoundingModeAttr matchRoundingModeAttr(llvm::Value *value)
Converts value to a rounding mode attribute.
void convertTargetTriple()
Converts target triple of the LLVM module to an MLIR target triple specification.
void convertArgAndResultAttrs(llvm::CallBase *call, ArgAndResultAttrsOpInterface attrsOp, ArrayRef< unsigned > immArgPositions={})
Converts the argument and result attributes attached to call and adds them to attrsOp.
LogicalResult convertModuleFlagsMetadata()
Converts !llvm.module.flags metadata.
void mapValue(llvm::Value *llvm, Value mlir)
Stores the mapping between an LLVM value and its MLIR counterpart.
Definition: ModuleImport.h:91
FailureOr< SmallVector< AccessGroupAttr > > lookupAccessGroupAttrs(const llvm::MDNode *node) const
Returns the access group attributes that map to the access group nodes starting from the access group...
LogicalResult convertGlobals()
Converts all global variables of the LLVM module to MLIR global variables.
void setIntegerOverflowFlags(llvm::Instruction *inst, Operation *op) const
Sets the integer overflow flags (nsw/nuw) attribute for the imported operation op given the original ...
LogicalResult convertCommandlineMetadata()
Converts !llvm.commandline metadata to the llvm.commandline LLVM ModuleOp attribute.
FPExceptionBehaviorAttr matchFPExceptionBehaviorAttr(llvm::Value *value)
Converts value to a FP exception behavior attribute.
void setNonNegFlag(llvm::Instruction *inst, Operation *op) const
Sets the nneg flag attribute for the imported operation op given the original instruction inst.
FailureOr< DereferenceableAttr > translateDereferenceableAttr(const llvm::MDNode *node, unsigned kindID)
Returns the dereferenceable attribute that corresponds to the given LLVM dereferenceable or dereferen...
LogicalResult convertDataLayout()
Converts the data layout of the LLVM module to an MLIR data layout specification.
IntegerAttr matchIntegerAttr(llvm::Value *value)
Converts value to an integer attribute. Asserts if the matching fails.
Helper class that translates an LLVM data layout string to an MLIR data layout specification.
StringRef getLastToken() const
Returns the last data layout token that has been processed before the data layout translation failed.
ArrayRef< StringRef > getUnhandledTokens() const
Returns the data layout tokens that have not been handled during the data layout translation.
DataLayoutSpecInterface getDataLayoutSpec() const
Returns the MLIR data layout specification translated from the LLVM data layout.
A helper class that converts llvm.loop metadata nodes into corresponding LoopAnnotationAttrs and llvm...
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:76
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:63
std::vector< StringRef > getAvailableDialects()
Return information about all available dialects in the registry in this context.
void loadAllAvailableDialects()
Load all dialects available in the registry in this context.
RAII guard to reset the insertion point of the builder when destroyed.
Definition: Builders.h:348
This class helps build Operations.
Definition: Builders.h:207
Block * createBlock(Region *parent, Region::iterator insertPt={}, TypeRange argTypes={}, ArrayRef< Location > locs={})
Add new block with 'argTypes' arguments and set the insertion point to the end of it.
Definition: Builders.cpp:429
void setInsertionPointToStart(Block *block)
Sets the insertion point to the start of the specified block.
Definition: Builders.h:431
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
Definition: Builders.h:398
void setInsertionPointToEnd(Block *block)
Sets the insertion point to the end of the specified block.
Definition: Builders.h:436
void setInsertionPointAfterValue(Value val)
Sets the insertion point to the node after the specified value.
Definition: Builders.h:421
void setInsertionPointAfter(Operation *op)
Sets the insertion point to the node after the specified operation, which will cause subsequent inser...
Definition: Builders.h:412
Block * getInsertionBlock() const
Return the block the current insertion point belongs to.
Definition: Builders.h:442
This class provides the API for ops that are known to be terminators.
Definition: OpDefinition.h:773
This provides public APIs that all operations should have.
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
Definition: Operation.h:749
Location getLoc()
The source location the operation was defined or derived from.
Definition: Operation.h:223
OpTy get() const
Allow accessing the internal op.
Definition: OwningOpRef.h:51
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition: Region.h:26
iterator end()
Definition: Region.h:56
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:74
MLIRContext * getContext() const
Return the MLIRContext in which this type was uniqued.
Definition: Types.cpp:35
bool isIntOrFloat() const
Return true if this is an integer (of any signedness) or a float type.
Definition: Types.cpp:116
This class provides an abstraction over the different types of ranges over Values.
Definition: ValueRange.h:387
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:96
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
Definition: Value.cpp:18
static DenseArrayAttrImpl get(MLIRContext *context, ArrayRef< int32_t > content)
Builder from ArrayRef<T>.
DominanceInfoNode * getNode(Block *a)
Return the dominance node from the Region containing block A.
Definition: Dominance.h:82
static llvm::ArrayRef< std::pair< llvm::Attribute::AttrKind, llvm::StringRef > > getAttrKindToNameMapping()
Returns a list of pairs that each hold a mapping from LLVM attribute kinds to their corresponding str...
FloatType getFloatType(MLIRContext *context, unsigned width)
Returns a supported MLIR floating point type of the given bit width or null if the bit width is not s...
bool isCompatibleVectorType(Type type)
Returns true if the given type is a vector type compatible with the LLVM dialect.
Definition: LLVMTypes.cpp:839
llvm::ElementCount getVectorNumElements(Type type)
Returns the element count of any LLVM-compatible vector type.
Definition: LLVMTypes.cpp:853
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
Definition: Matchers.h:344
detail::InFlightRemark failed(Location loc, RemarkOpts opts)
Report an optimization remark that failed.
Definition: Remarks.h:491
Include the generated interface declarations.
bool matchPattern(Value value, const Pattern &pattern)
Entry point for matching a pattern over a Value.
Definition: Matchers.h:490
InFlightDiagnostic emitWarning(Location loc)
Utility method to emit a warning message using this location.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
detail::constant_op_matcher m_Constant()
Matches a constant foldable operation.
Definition: Matchers.h:369
OwningOpRef< ModuleOp > translateLLVMIRToModule(std::unique_ptr< llvm::Module > llvmModule, MLIRContext *context, bool emitExpensiveWarnings=true, bool dropDICompositeTypeElements=false, bool loadAllDialects=true, bool preferUnregisteredIntrinsics=false, bool importStructsAsLiterals=false)
Translates the LLVM module into an MLIR module living in the given context.