MLIR  19.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 
16 
17 #include "AttrKindDetail.h"
18 #include "DataLayoutImporter.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"
28 
29 #include "llvm/ADT/DepthFirstIterator.h"
30 #include "llvm/ADT/PostOrderIterator.h"
31 #include "llvm/ADT/ScopeExit.h"
32 #include "llvm/ADT/StringSet.h"
33 #include "llvm/ADT/TypeSwitch.h"
34 #include "llvm/IR/Comdat.h"
35 #include "llvm/IR/Constants.h"
36 #include "llvm/IR/InlineAsm.h"
37 #include "llvm/IR/InstIterator.h"
38 #include "llvm/IR/Instructions.h"
39 #include "llvm/IR/IntrinsicInst.h"
40 #include "llvm/IR/Metadata.h"
41 #include "llvm/IR/Operator.h"
42 #include "llvm/Support/ModRef.h"
43 
44 using namespace mlir;
45 using namespace mlir::LLVM;
46 using namespace mlir::LLVM::detail;
47 
48 #include "mlir/Dialect/LLVMIR/LLVMConversionEnumsFromLLVM.inc"
49 
50 // Utility to print an LLVM value as a string for passing to emitError().
51 // FIXME: Diagnostic should be able to natively handle types that have
52 // operator << (raw_ostream&) defined.
53 static std::string diag(const llvm::Value &value) {
54  std::string str;
55  llvm::raw_string_ostream os(str);
56  os << value;
57  return os.str();
58 }
59 
60 // Utility to print an LLVM metadata node as a string for passing
61 // to emitError(). The module argument is needed to print the nodes
62 // canonically numbered.
63 static std::string diagMD(const llvm::Metadata *node,
64  const llvm::Module *module) {
65  std::string str;
66  llvm::raw_string_ostream os(str);
67  node->print(os, module, /*IsForDebug=*/true);
68  return os.str();
69 }
70 
71 /// Returns the name of the global_ctors global variables.
72 static constexpr StringRef getGlobalCtorsVarName() {
73  return "llvm.global_ctors";
74 }
75 
76 /// Returns the name of the global_dtors global variables.
77 static constexpr StringRef getGlobalDtorsVarName() {
78  return "llvm.global_dtors";
79 }
80 
81 /// Returns the symbol name for the module-level comdat operation. It must not
82 /// conflict with the user namespace.
83 static constexpr StringRef getGlobalComdatOpName() {
84  return "__llvm_global_comdat";
85 }
86 
87 /// Converts the sync scope identifier of `inst` to the string representation
88 /// necessary to build an atomic LLVM dialect operation. Returns the empty
89 /// string if the operation has either no sync scope or the default system-level
90 /// sync scope attached. The atomic operations only set their sync scope
91 /// attribute if they have a non-default sync scope attached.
92 static StringRef getLLVMSyncScope(llvm::Instruction *inst) {
93  std::optional<llvm::SyncScope::ID> syncScopeID =
94  llvm::getAtomicSyncScopeID(inst);
95  if (!syncScopeID)
96  return "";
97 
98  // Search the sync scope name for the given identifier. The default
99  // system-level sync scope thereby maps to the empty string.
100  SmallVector<StringRef> syncScopeName;
101  llvm::LLVMContext &llvmContext = inst->getContext();
102  llvmContext.getSyncScopeNames(syncScopeName);
103  auto *it = llvm::find_if(syncScopeName, [&](StringRef name) {
104  return *syncScopeID == llvmContext.getOrInsertSyncScopeID(name);
105  });
106  if (it != syncScopeName.end())
107  return *it;
108  llvm_unreachable("incorrect sync scope identifier");
109 }
110 
111 /// Converts an array of unsigned indices to a signed integer position array.
113  SmallVector<int64_t> position;
114  llvm::append_range(position, indices);
115  return position;
116 }
117 
118 /// Converts the LLVM instructions that have a generated MLIR builder. Using a
119 /// static implementation method called from the module import ensures the
120 /// builders have to use the `moduleImport` argument and cannot directly call
121 /// import methods. As a result, both the intrinsic and the instruction MLIR
122 /// builders have to use the `moduleImport` argument and none of them has direct
123 /// access to the private module import methods.
125  llvm::Instruction *inst,
126  ModuleImport &moduleImport,
127  LLVMImportInterface &iface) {
128  // Copy the operands to an LLVM operands array reference for conversion.
129  SmallVector<llvm::Value *> operands(inst->operands());
130  ArrayRef<llvm::Value *> llvmOperands(operands);
131 
132  // Convert all instructions that provide an MLIR builder.
133  if (iface.isConvertibleInstruction(inst->getOpcode()))
134  return iface.convertInstruction(odsBuilder, inst, llvmOperands,
135  moduleImport);
136  // TODO: Implement the `convertInstruction` hooks in the
137  // `LLVMDialectLLVMIRImportInterface` and move the following include there.
138 #include "mlir/Dialect/LLVMIR/LLVMOpFromLLVMIRConversions.inc"
139  return failure();
140 }
141 
142 /// Get a topologically sorted list of blocks for the given basic blocks.
146  for (llvm::BasicBlock *basicBlock : basicBlocks) {
147  if (!blocks.contains(basicBlock)) {
148  llvm::ReversePostOrderTraversal<llvm::BasicBlock *> traversal(basicBlock);
149  blocks.insert(traversal.begin(), traversal.end());
150  }
151  }
152  assert(blocks.size() == basicBlocks.size() && "some blocks are not sorted");
153  return blocks;
154 }
155 
156 ModuleImport::ModuleImport(ModuleOp mlirModule,
157  std::unique_ptr<llvm::Module> llvmModule,
158  bool emitExpensiveWarnings,
159  bool importEmptyDICompositeTypes)
160  : builder(mlirModule->getContext()), context(mlirModule->getContext()),
161  mlirModule(mlirModule), llvmModule(std::move(llvmModule)),
162  iface(mlirModule->getContext()),
163  typeTranslator(*mlirModule->getContext()),
164  debugImporter(std::make_unique<DebugImporter>(
165  mlirModule, importEmptyDICompositeTypes)),
166  loopAnnotationImporter(
167  std::make_unique<LoopAnnotationImporter>(*this, builder)),
168  emitExpensiveWarnings(emitExpensiveWarnings) {
169  builder.setInsertionPointToStart(mlirModule.getBody());
170 }
171 
172 ComdatOp ModuleImport::getGlobalComdatOp() {
173  if (globalComdatOp)
174  return globalComdatOp;
175 
176  OpBuilder::InsertionGuard guard(builder);
177  builder.setInsertionPointToEnd(mlirModule.getBody());
178  globalComdatOp =
179  builder.create<ComdatOp>(mlirModule.getLoc(), getGlobalComdatOpName());
180  globalInsertionOp = globalComdatOp;
181  return globalComdatOp;
182 }
183 
184 LogicalResult ModuleImport::processTBAAMetadata(const llvm::MDNode *node) {
185  Location loc = mlirModule.getLoc();
186 
187  // If `node` is a valid TBAA root node, then return its optional identity
188  // string, otherwise return failure.
189  auto getIdentityIfRootNode =
190  [&](const llvm::MDNode *node) -> FailureOr<std::optional<StringRef>> {
191  // Root node, e.g.:
192  // !0 = !{!"Simple C/C++ TBAA"}
193  // !1 = !{}
194  if (node->getNumOperands() > 1)
195  return failure();
196  // If the operand is MDString, then assume that this is a root node.
197  if (node->getNumOperands() == 1)
198  if (const auto *op0 = dyn_cast<const llvm::MDString>(node->getOperand(0)))
199  return std::optional<StringRef>{op0->getString()};
200  return std::optional<StringRef>{};
201  };
202 
203  // If `node` looks like a TBAA type descriptor metadata,
204  // then return true, if it is a valid node, and false otherwise.
205  // If it does not look like a TBAA type descriptor metadata, then
206  // return std::nullopt.
207  // If `identity` and `memberTypes/Offsets` are non-null, then they will
208  // contain the converted metadata operands for a valid TBAA node (i.e. when
209  // true is returned).
210  auto isTypeDescriptorNode = [&](const llvm::MDNode *node,
211  StringRef *identity = nullptr,
213  nullptr) -> std::optional<bool> {
214  unsigned numOperands = node->getNumOperands();
215  // Type descriptor, e.g.:
216  // !1 = !{!"int", !0, /*optional*/i64 0} /* scalar int type */
217  // !2 = !{!"agg_t", !1, i64 0} /* struct agg_t { int x; } */
218  if (numOperands < 2)
219  return std::nullopt;
220 
221  // TODO: support "new" format (D41501) for type descriptors,
222  // where the first operand is an MDNode.
223  const auto *identityNode =
224  dyn_cast<const llvm::MDString>(node->getOperand(0));
225  if (!identityNode)
226  return std::nullopt;
227 
228  // This should be a type descriptor node.
229  if (identity)
230  *identity = identityNode->getString();
231 
232  for (unsigned pairNum = 0, e = numOperands / 2; pairNum < e; ++pairNum) {
233  const auto *memberNode =
234  dyn_cast<const llvm::MDNode>(node->getOperand(2 * pairNum + 1));
235  if (!memberNode) {
236  emitError(loc) << "operand '" << 2 * pairNum + 1 << "' must be MDNode: "
237  << diagMD(node, llvmModule.get());
238  return false;
239  }
240  int64_t offset = 0;
241  if (2 * pairNum + 2 >= numOperands) {
242  // Allow for optional 0 offset in 2-operand nodes.
243  if (numOperands != 2) {
244  emitError(loc) << "missing member offset: "
245  << diagMD(node, llvmModule.get());
246  return false;
247  }
248  } else {
249  auto *offsetCI = llvm::mdconst::dyn_extract<llvm::ConstantInt>(
250  node->getOperand(2 * pairNum + 2));
251  if (!offsetCI) {
252  emitError(loc) << "operand '" << 2 * pairNum + 2
253  << "' must be ConstantInt: "
254  << diagMD(node, llvmModule.get());
255  return false;
256  }
257  offset = offsetCI->getZExtValue();
258  }
259 
260  if (members)
261  members->push_back(TBAAMemberAttr::get(
262  cast<TBAANodeAttr>(tbaaMapping.lookup(memberNode)), offset));
263  }
264 
265  return true;
266  };
267 
268  // If `node` looks like a TBAA access tag metadata,
269  // then return true, if it is a valid node, and false otherwise.
270  // If it does not look like a TBAA access tag metadata, then
271  // return std::nullopt.
272  // If the other arguments are non-null, then they will contain
273  // the converted metadata operands for a valid TBAA node (i.e. when true is
274  // returned).
275  auto isTagNode = [&](const llvm::MDNode *node,
276  TBAATypeDescriptorAttr *baseAttr = nullptr,
277  TBAATypeDescriptorAttr *accessAttr = nullptr,
278  int64_t *offset = nullptr,
279  bool *isConstant = nullptr) -> std::optional<bool> {
280  // Access tag, e.g.:
281  // !3 = !{!1, !1, i64 0} /* scalar int access */
282  // !4 = !{!2, !1, i64 0} /* agg_t::x access */
283  //
284  // Optional 4th argument is ConstantInt 0/1 identifying whether
285  // the location being accessed is "constant" (see for details:
286  // https://llvm.org/docs/LangRef.html#representation).
287  unsigned numOperands = node->getNumOperands();
288  if (numOperands != 3 && numOperands != 4)
289  return std::nullopt;
290  const auto *baseMD = dyn_cast<const llvm::MDNode>(node->getOperand(0));
291  const auto *accessMD = dyn_cast<const llvm::MDNode>(node->getOperand(1));
292  auto *offsetCI =
293  llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(2));
294  if (!baseMD || !accessMD || !offsetCI)
295  return std::nullopt;
296  // TODO: support "new" TBAA format, if needed (see D41501).
297  // In the "old" format the first operand of the access type
298  // metadata is MDString. We have to distinguish the formats,
299  // because access tags have the same structure, but different
300  // meaning for the operands.
301  if (accessMD->getNumOperands() < 1 ||
302  !isa<llvm::MDString>(accessMD->getOperand(0)))
303  return std::nullopt;
304  bool isConst = false;
305  if (numOperands == 4) {
306  auto *isConstantCI =
307  llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(3));
308  if (!isConstantCI) {
309  emitError(loc) << "operand '3' must be ConstantInt: "
310  << diagMD(node, llvmModule.get());
311  return false;
312  }
313  isConst = isConstantCI->getValue()[0];
314  }
315  if (baseAttr)
316  *baseAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(baseMD));
317  if (accessAttr)
318  *accessAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(accessMD));
319  if (offset)
320  *offset = offsetCI->getZExtValue();
321  if (isConstant)
322  *isConstant = isConst;
323  return true;
324  };
325 
326  // Do a post-order walk over the TBAA Graph. Since a correct TBAA Graph is a
327  // DAG, a post-order walk guarantees that we convert any metadata node we
328  // depend on, prior to converting the current node.
331  workList.push_back(node);
332  while (!workList.empty()) {
333  const llvm::MDNode *current = workList.back();
334  if (tbaaMapping.contains(current)) {
335  // Already converted. Just pop from the worklist.
336  workList.pop_back();
337  continue;
338  }
339 
340  // If any child of this node is not yet converted, don't pop the current
341  // node from the worklist but push the not-yet-converted children in the
342  // front of the worklist.
343  bool anyChildNotConverted = false;
344  for (const llvm::MDOperand &operand : current->operands())
345  if (auto *childNode = dyn_cast_or_null<const llvm::MDNode>(operand.get()))
346  if (!tbaaMapping.contains(childNode)) {
347  workList.push_back(childNode);
348  anyChildNotConverted = true;
349  }
350 
351  if (anyChildNotConverted) {
352  // If this is the second time we failed to convert an element in the
353  // worklist it must be because a child is dependent on it being converted
354  // and we have a cycle in the graph. Cycles are not allowed in TBAA
355  // graphs.
356  if (!seen.insert(current).second)
357  return emitError(loc) << "has cycle in TBAA graph: "
358  << diagMD(current, llvmModule.get());
359 
360  continue;
361  }
362 
363  // Otherwise simply import the current node.
364  workList.pop_back();
365 
366  FailureOr<std::optional<StringRef>> rootNodeIdentity =
367  getIdentityIfRootNode(current);
368  if (succeeded(rootNodeIdentity)) {
369  StringAttr stringAttr = *rootNodeIdentity
370  ? builder.getStringAttr(**rootNodeIdentity)
371  : nullptr;
372  // The root nodes do not have operands, so we can create
373  // the TBAARootAttr on the first walk.
374  tbaaMapping.insert({current, builder.getAttr<TBAARootAttr>(stringAttr)});
375  continue;
376  }
377 
378  StringRef identity;
380  if (std::optional<bool> isValid =
381  isTypeDescriptorNode(current, &identity, &members)) {
382  assert(isValid.value() && "type descriptor node must be valid");
383 
384  tbaaMapping.insert({current, builder.getAttr<TBAATypeDescriptorAttr>(
385  identity, members)});
386  continue;
387  }
388 
389  TBAATypeDescriptorAttr baseAttr, accessAttr;
390  int64_t offset;
391  bool isConstant;
392  if (std::optional<bool> isValid =
393  isTagNode(current, &baseAttr, &accessAttr, &offset, &isConstant)) {
394  assert(isValid.value() && "access tag node must be valid");
395  tbaaMapping.insert(
396  {current, builder.getAttr<TBAATagAttr>(baseAttr, accessAttr, offset,
397  isConstant)});
398  continue;
399  }
400 
401  return emitError(loc) << "unsupported TBAA node format: "
402  << diagMD(current, llvmModule.get());
403  }
404  return success();
405 }
406 
408 ModuleImport::processAccessGroupMetadata(const llvm::MDNode *node) {
409  Location loc = mlirModule.getLoc();
410  if (failed(loopAnnotationImporter->translateAccessGroup(node, loc)))
411  return emitError(loc) << "unsupported access group node: "
412  << diagMD(node, llvmModule.get());
413  return success();
414 }
415 
417 ModuleImport::processAliasScopeMetadata(const llvm::MDNode *node) {
418  Location loc = mlirModule.getLoc();
419  // Helper that verifies the node has a self reference operand.
420  auto verifySelfRef = [](const llvm::MDNode *node) {
421  return node->getNumOperands() != 0 &&
422  node == dyn_cast<llvm::MDNode>(node->getOperand(0));
423  };
424  // Helper that verifies the given operand is a string or does not exist.
425  auto verifyDescription = [](const llvm::MDNode *node, unsigned idx) {
426  return idx >= node->getNumOperands() ||
427  isa<llvm::MDString>(node->getOperand(idx));
428  };
429  // Helper that creates an alias scope domain attribute.
430  auto createAliasScopeDomainOp = [&](const llvm::MDNode *aliasDomain) {
431  StringAttr description = nullptr;
432  if (aliasDomain->getNumOperands() >= 2)
433  if (auto *operand = dyn_cast<llvm::MDString>(aliasDomain->getOperand(1)))
434  description = builder.getStringAttr(operand->getString());
435  return builder.getAttr<AliasScopeDomainAttr>(
436  DistinctAttr::create(builder.getUnitAttr()), description);
437  };
438 
439  // Collect the alias scopes and domains to translate them.
440  for (const llvm::MDOperand &operand : node->operands()) {
441  if (const auto *scope = dyn_cast<llvm::MDNode>(operand)) {
442  llvm::AliasScopeNode aliasScope(scope);
443  const llvm::MDNode *domain = aliasScope.getDomain();
444 
445  // Verify the scope node points to valid scope metadata which includes
446  // verifying its domain. Perform the verification before looking it up in
447  // the alias scope mapping since it could have been inserted as a domain
448  // node before.
449  if (!verifySelfRef(scope) || !domain || !verifyDescription(scope, 2))
450  return emitError(loc) << "unsupported alias scope node: "
451  << diagMD(scope, llvmModule.get());
452  if (!verifySelfRef(domain) || !verifyDescription(domain, 1))
453  return emitError(loc) << "unsupported alias domain node: "
454  << diagMD(domain, llvmModule.get());
455 
456  if (aliasScopeMapping.contains(scope))
457  continue;
458 
459  // Convert the domain metadata node if it has not been translated before.
460  auto it = aliasScopeMapping.find(aliasScope.getDomain());
461  if (it == aliasScopeMapping.end()) {
462  auto aliasScopeDomainOp = createAliasScopeDomainOp(domain);
463  it = aliasScopeMapping.try_emplace(domain, aliasScopeDomainOp).first;
464  }
465 
466  // Convert the scope metadata node if it has not been converted before.
467  StringAttr description = nullptr;
468  if (!aliasScope.getName().empty())
469  description = builder.getStringAttr(aliasScope.getName());
470  auto aliasScopeOp = builder.getAttr<AliasScopeAttr>(
472  cast<AliasScopeDomainAttr>(it->second), description);
473  aliasScopeMapping.try_emplace(aliasScope.getNode(), aliasScopeOp);
474  }
475  }
476  return success();
477 }
478 
480 ModuleImport::lookupAliasScopeAttrs(const llvm::MDNode *node) const {
481  SmallVector<AliasScopeAttr> aliasScopes;
482  aliasScopes.reserve(node->getNumOperands());
483  for (const llvm::MDOperand &operand : node->operands()) {
484  auto *node = cast<llvm::MDNode>(operand.get());
485  aliasScopes.push_back(
486  dyn_cast_or_null<AliasScopeAttr>(aliasScopeMapping.lookup(node)));
487  }
488  // Return failure if one of the alias scope lookups failed.
489  if (llvm::is_contained(aliasScopes, nullptr))
490  return failure();
491  return aliasScopes;
492 }
493 
494 void ModuleImport::addDebugIntrinsic(llvm::CallInst *intrinsic) {
495  debugIntrinsics.insert(intrinsic);
496 }
497 
499  for (const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
500  if (named.getName() != "llvm.linker.options")
501  continue;
502  // llvm.linker.options operands are lists of strings.
503  for (const llvm::MDNode *md : named.operands()) {
505  options.reserve(md->getNumOperands());
506  for (const llvm::MDOperand &option : md->operands())
507  options.push_back(cast<llvm::MDString>(option)->getString());
508  builder.create<LLVM::LinkerOptionsOp>(mlirModule.getLoc(),
509  builder.getStrArrayAttr(options));
510  }
511  }
512  return success();
513 }
514 
516  OpBuilder::InsertionGuard guard(builder);
517  builder.setInsertionPointToEnd(mlirModule.getBody());
518  for (const llvm::Function &func : llvmModule->functions()) {
519  for (const llvm::Instruction &inst : llvm::instructions(func)) {
520  // Convert access group metadata nodes.
521  if (llvm::MDNode *node =
522  inst.getMetadata(llvm::LLVMContext::MD_access_group))
523  if (failed(processAccessGroupMetadata(node)))
524  return failure();
525 
526  // Convert alias analysis metadata nodes.
527  llvm::AAMDNodes aliasAnalysisNodes = inst.getAAMetadata();
528  if (!aliasAnalysisNodes)
529  continue;
530  if (aliasAnalysisNodes.TBAA)
531  if (failed(processTBAAMetadata(aliasAnalysisNodes.TBAA)))
532  return failure();
533  if (aliasAnalysisNodes.Scope)
534  if (failed(processAliasScopeMetadata(aliasAnalysisNodes.Scope)))
535  return failure();
536  if (aliasAnalysisNodes.NoAlias)
537  if (failed(processAliasScopeMetadata(aliasAnalysisNodes.NoAlias)))
538  return failure();
539  }
540  }
542  return failure();
543  return success();
544 }
545 
546 void ModuleImport::processComdat(const llvm::Comdat *comdat) {
547  if (comdatMapping.contains(comdat))
548  return;
549 
550  ComdatOp comdatOp = getGlobalComdatOp();
551  OpBuilder::InsertionGuard guard(builder);
552  builder.setInsertionPointToEnd(&comdatOp.getBody().back());
553  auto selectorOp = builder.create<ComdatSelectorOp>(
554  mlirModule.getLoc(), comdat->getName(),
555  convertComdatFromLLVM(comdat->getSelectionKind()));
556  auto symbolRef =
558  FlatSymbolRefAttr::get(selectorOp.getSymNameAttr()));
559  comdatMapping.try_emplace(comdat, symbolRef);
560 }
561 
563  for (llvm::GlobalVariable &globalVar : llvmModule->globals())
564  if (globalVar.hasComdat())
565  processComdat(globalVar.getComdat());
566  for (llvm::Function &func : llvmModule->functions())
567  if (func.hasComdat())
568  processComdat(func.getComdat());
569  return success();
570 }
571 
573  for (llvm::GlobalVariable &globalVar : llvmModule->globals()) {
574  if (globalVar.getName() == getGlobalCtorsVarName() ||
575  globalVar.getName() == getGlobalDtorsVarName()) {
576  if (failed(convertGlobalCtorsAndDtors(&globalVar))) {
577  return emitError(UnknownLoc::get(context))
578  << "unhandled global variable: " << diag(globalVar);
579  }
580  continue;
581  }
582  if (failed(convertGlobal(&globalVar))) {
583  return emitError(UnknownLoc::get(context))
584  << "unhandled global variable: " << diag(globalVar);
585  }
586  }
587  return success();
588 }
589 
591  Location loc = mlirModule.getLoc();
592  DataLayoutImporter dataLayoutImporter(context, llvmModule->getDataLayout());
593  if (!dataLayoutImporter.getDataLayout())
594  return emitError(loc, "cannot translate data layout: ")
595  << dataLayoutImporter.getLastToken();
596 
597  for (StringRef token : dataLayoutImporter.getUnhandledTokens())
598  emitWarning(loc, "unhandled data layout token: ") << token;
599 
600  mlirModule->setAttr(DLTIDialect::kDataLayoutAttrName,
601  dataLayoutImporter.getDataLayout());
602  return success();
603 }
604 
606  for (llvm::Function &func : llvmModule->functions())
607  if (failed(processFunction(&func)))
608  return failure();
609  return success();
610 }
611 
612 void ModuleImport::setNonDebugMetadataAttrs(llvm::Instruction *inst,
613  Operation *op) {
615  inst->getAllMetadataOtherThanDebugLoc(allMetadata);
616  for (auto &[kind, node] : allMetadata) {
617  if (!iface.isConvertibleMetadata(kind))
618  continue;
619  if (failed(iface.setMetadataAttrs(builder, kind, node, op, *this))) {
620  if (emitExpensiveWarnings) {
621  Location loc = debugImporter->translateLoc(inst->getDebugLoc());
622  emitWarning(loc) << "unhandled metadata: "
623  << diagMD(node, llvmModule.get()) << " on "
624  << diag(*inst);
625  }
626  }
627  }
628 }
629 
630 void ModuleImport::setIntegerOverflowFlags(llvm::Instruction *inst,
631  Operation *op) const {
632  auto iface = cast<IntegerOverflowFlagsInterface>(op);
633 
634  IntegerOverflowFlags value = {};
635  value = bitEnumSet(value, IntegerOverflowFlags::nsw, inst->hasNoSignedWrap());
636  value =
637  bitEnumSet(value, IntegerOverflowFlags::nuw, inst->hasNoUnsignedWrap());
638 
639  iface.setOverflowFlags(value);
640 }
641 
642 void ModuleImport::setFastmathFlagsAttr(llvm::Instruction *inst,
643  Operation *op) const {
644  auto iface = cast<FastmathFlagsInterface>(op);
645 
646  // Even if the imported operation implements the fastmath interface, the
647  // original instruction may not have fastmath flags set. Exit if an
648  // instruction, such as a non floating-point function call, does not have
649  // fastmath flags.
650  if (!isa<llvm::FPMathOperator>(inst))
651  return;
652  llvm::FastMathFlags flags = inst->getFastMathFlags();
653 
654  // Set the fastmath bits flag-by-flag.
655  FastmathFlags value = {};
656  value = bitEnumSet(value, FastmathFlags::nnan, flags.noNaNs());
657  value = bitEnumSet(value, FastmathFlags::ninf, flags.noInfs());
658  value = bitEnumSet(value, FastmathFlags::nsz, flags.noSignedZeros());
659  value = bitEnumSet(value, FastmathFlags::arcp, flags.allowReciprocal());
660  value = bitEnumSet(value, FastmathFlags::contract, flags.allowContract());
661  value = bitEnumSet(value, FastmathFlags::afn, flags.approxFunc());
662  value = bitEnumSet(value, FastmathFlags::reassoc, flags.allowReassoc());
663  FastmathFlagsAttr attr = FastmathFlagsAttr::get(builder.getContext(), value);
664  iface->setAttr(iface.getFastmathAttrName(), attr);
665 }
666 
667 /// Returns if `type` is a scalar integer or floating-point type.
668 static bool isScalarType(Type type) {
669  return isa<IntegerType, FloatType>(type);
670 }
671 
672 /// Returns `type` if it is a builtin integer or floating-point vector type that
673 /// can be used to create an attribute or nullptr otherwise. If provided,
674 /// `arrayShape` is added to the shape of the vector to create an attribute that
675 /// matches an array of vectors.
676 static Type getVectorTypeForAttr(Type type, ArrayRef<int64_t> arrayShape = {}) {
677  if (!LLVM::isCompatibleVectorType(type))
678  return {};
679 
680  llvm::ElementCount numElements = LLVM::getVectorNumElements(type);
681  if (numElements.isScalable()) {
683  << "scalable vectors not supported";
684  return {};
685  }
686 
687  // An LLVM dialect vector can only contain scalars.
688  Type elementType = LLVM::getVectorElementType(type);
689  if (!isScalarType(elementType))
690  return {};
691 
692  SmallVector<int64_t> shape(arrayShape.begin(), arrayShape.end());
693  shape.push_back(numElements.getKnownMinValue());
694  return VectorType::get(shape, elementType);
695 }
696 
697 Type ModuleImport::getBuiltinTypeForAttr(Type type) {
698  if (!type)
699  return {};
700 
701  // Return builtin integer and floating-point types as is.
702  if (isScalarType(type))
703  return type;
704 
705  // Return builtin vectors of integer and floating-point types as is.
706  if (Type vectorType = getVectorTypeForAttr(type))
707  return vectorType;
708 
709  // Multi-dimensional array types are converted to tensors or vectors,
710  // depending on the innermost type being a scalar or a vector.
711  SmallVector<int64_t> arrayShape;
712  while (auto arrayType = dyn_cast<LLVMArrayType>(type)) {
713  arrayShape.push_back(arrayType.getNumElements());
714  type = arrayType.getElementType();
715  }
716  if (isScalarType(type))
717  return RankedTensorType::get(arrayShape, type);
718  return getVectorTypeForAttr(type, arrayShape);
719 }
720 
721 /// Returns an integer or float attribute for the provided scalar constant
722 /// `constScalar` or nullptr if the conversion fails.
723 static TypedAttr getScalarConstantAsAttr(OpBuilder &builder,
724  llvm::Constant *constScalar) {
725  MLIRContext *context = builder.getContext();
726 
727  // Convert scalar intergers.
728  if (auto *constInt = dyn_cast<llvm::ConstantInt>(constScalar)) {
729  return builder.getIntegerAttr(
730  IntegerType::get(context, constInt->getBitWidth()),
731  constInt->getValue());
732  }
733 
734  // Convert scalar floats.
735  if (auto *constFloat = dyn_cast<llvm::ConstantFP>(constScalar)) {
736  llvm::Type *type = constFloat->getType();
737  FloatType floatType =
738  type->isBFloatTy()
739  ? FloatType::getBF16(context)
740  : LLVM::detail::getFloatType(context, type->getScalarSizeInBits());
741  if (!floatType) {
743  << "unexpected floating-point type";
744  return {};
745  }
746  return builder.getFloatAttr(floatType, constFloat->getValueAPF());
747  }
748  return {};
749 }
750 
751 /// Returns an integer or float attribute array for the provided constant
752 /// sequence `constSequence` or nullptr if the conversion fails.
755  llvm::ConstantDataSequential *constSequence) {
756  SmallVector<Attribute> elementAttrs;
757  elementAttrs.reserve(constSequence->getNumElements());
758  for (auto idx : llvm::seq<int64_t>(0, constSequence->getNumElements())) {
759  llvm::Constant *constElement = constSequence->getElementAsConstant(idx);
760  elementAttrs.push_back(getScalarConstantAsAttr(builder, constElement));
761  }
762  return elementAttrs;
763 }
764 
765 Attribute ModuleImport::getConstantAsAttr(llvm::Constant *constant) {
766  // Convert scalar constants.
767  if (Attribute scalarAttr = getScalarConstantAsAttr(builder, constant))
768  return scalarAttr;
769 
770  // Convert function references.
771  if (auto *func = dyn_cast<llvm::Function>(constant))
772  return SymbolRefAttr::get(builder.getContext(), func->getName());
773 
774  // Returns the static shape of the provided type if possible.
775  auto getConstantShape = [&](llvm::Type *type) {
776  return llvm::dyn_cast_if_present<ShapedType>(
777  getBuiltinTypeForAttr(convertType(type)));
778  };
779 
780  // Convert one-dimensional constant arrays or vectors that store 1/2/4/8-byte
781  // integer or half/bfloat/float/double values.
782  if (auto *constArray = dyn_cast<llvm::ConstantDataSequential>(constant)) {
783  if (constArray->isString())
784  return builder.getStringAttr(constArray->getAsString());
785  auto shape = getConstantShape(constArray->getType());
786  if (!shape)
787  return {};
788  // Convert splat constants to splat elements attributes.
789  auto *constVector = dyn_cast<llvm::ConstantDataVector>(constant);
790  if (constVector && constVector->isSplat()) {
791  // A vector is guaranteed to have at least size one.
793  builder, constVector->getElementAsConstant(0));
794  return SplatElementsAttr::get(shape, splatAttr);
795  }
796  // Convert non-splat constants to dense elements attributes.
797  SmallVector<Attribute> elementAttrs =
798  getSequenceConstantAsAttrs(builder, constArray);
799  return DenseElementsAttr::get(shape, elementAttrs);
800  }
801 
802  // Convert multi-dimensional constant aggregates that store all kinds of
803  // integer and floating-point types.
804  if (auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(constant)) {
805  auto shape = getConstantShape(constAggregate->getType());
806  if (!shape)
807  return {};
808  // Collect the aggregate elements in depths first order.
809  SmallVector<Attribute> elementAttrs;
810  SmallVector<llvm::Constant *> workList = {constAggregate};
811  while (!workList.empty()) {
812  llvm::Constant *current = workList.pop_back_val();
813  // Append any nested aggregates in reverse order to ensure the head
814  // element of the nested aggregates is at the back of the work list.
815  if (auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(current)) {
816  for (auto idx :
817  reverse(llvm::seq<int64_t>(0, constAggregate->getNumOperands())))
818  workList.push_back(constAggregate->getAggregateElement(idx));
819  continue;
820  }
821  // Append the elements of nested constant arrays or vectors that store
822  // 1/2/4/8-byte integer or half/bfloat/float/double values.
823  if (auto *constArray = dyn_cast<llvm::ConstantDataSequential>(current)) {
824  SmallVector<Attribute> attrs =
825  getSequenceConstantAsAttrs(builder, constArray);
826  elementAttrs.append(attrs.begin(), attrs.end());
827  continue;
828  }
829  // Append nested scalar constants that store all kinds of integer and
830  // floating-point types.
831  if (Attribute scalarAttr = getScalarConstantAsAttr(builder, current)) {
832  elementAttrs.push_back(scalarAttr);
833  continue;
834  }
835  // Bail if the aggregate contains a unsupported constant type such as a
836  // constant expression.
837  return {};
838  }
839  return DenseElementsAttr::get(shape, elementAttrs);
840  }
841 
842  // Convert zero aggregates.
843  if (auto *constZero = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
844  auto shape = llvm::dyn_cast_if_present<ShapedType>(
845  getBuiltinTypeForAttr(convertType(constZero->getType())));
846  if (!shape)
847  return {};
848  // Convert zero aggregates with a static shape to splat elements attributes.
849  Attribute splatAttr = builder.getZeroAttr(shape.getElementType());
850  assert(splatAttr && "expected non-null zero attribute for scalar types");
851  return SplatElementsAttr::get(shape, splatAttr);
852  }
853  return {};
854 }
855 
856 LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) {
857  // Insert the global after the last one or at the start of the module.
858  OpBuilder::InsertionGuard guard(builder);
859  if (!globalInsertionOp)
860  builder.setInsertionPointToStart(mlirModule.getBody());
861  else
862  builder.setInsertionPointAfter(globalInsertionOp);
863 
864  Attribute valueAttr;
865  if (globalVar->hasInitializer())
866  valueAttr = getConstantAsAttr(globalVar->getInitializer());
867  Type type = convertType(globalVar->getValueType());
868 
869  uint64_t alignment = 0;
870  llvm::MaybeAlign maybeAlign = globalVar->getAlign();
871  if (maybeAlign.has_value()) {
872  llvm::Align align = *maybeAlign;
873  alignment = align.value();
874  }
875 
876  // Get the global expression associated with this global variable and convert
877  // it.
878  DIGlobalVariableExpressionAttr globalExpressionAttr;
880  globalVar->getDebugInfo(globalExpressions);
881 
882  // There should only be a single global expression.
883  if (!globalExpressions.empty())
884  globalExpressionAttr =
885  debugImporter->translateGlobalVariableExpression(globalExpressions[0]);
886 
887  GlobalOp globalOp = builder.create<GlobalOp>(
888  mlirModule.getLoc(), type, globalVar->isConstant(),
889  convertLinkageFromLLVM(globalVar->getLinkage()), globalVar->getName(),
890  valueAttr, alignment, /*addr_space=*/globalVar->getAddressSpace(),
891  /*dso_local=*/globalVar->isDSOLocal(),
892  /*thread_local=*/globalVar->isThreadLocal(), /*comdat=*/SymbolRefAttr(),
893  /*attrs=*/ArrayRef<NamedAttribute>(), /*dbgExpr=*/globalExpressionAttr);
894  globalInsertionOp = globalOp;
895 
896  if (globalVar->hasInitializer() && !valueAttr) {
897  clearRegionState();
898  Block *block = builder.createBlock(&globalOp.getInitializerRegion());
899  setConstantInsertionPointToStart(block);
900  FailureOr<Value> initializer =
901  convertConstantExpr(globalVar->getInitializer());
902  if (failed(initializer))
903  return failure();
904  builder.create<ReturnOp>(globalOp.getLoc(), *initializer);
905  }
906  if (globalVar->hasAtLeastLocalUnnamedAddr()) {
907  globalOp.setUnnamedAddr(
908  convertUnnamedAddrFromLLVM(globalVar->getUnnamedAddr()));
909  }
910  if (globalVar->hasSection())
911  globalOp.setSection(globalVar->getSection());
912  globalOp.setVisibility_(
913  convertVisibilityFromLLVM(globalVar->getVisibility()));
914 
915  if (globalVar->hasComdat())
916  globalOp.setComdatAttr(comdatMapping.lookup(globalVar->getComdat()));
917 
918  return success();
919 }
920 
922 ModuleImport::convertGlobalCtorsAndDtors(llvm::GlobalVariable *globalVar) {
923  if (!globalVar->hasInitializer() || !globalVar->hasAppendingLinkage())
924  return failure();
925  auto *initializer =
926  dyn_cast<llvm::ConstantArray>(globalVar->getInitializer());
927  if (!initializer)
928  return failure();
929 
931  SmallVector<int32_t> priorities;
932  for (llvm::Value *operand : initializer->operands()) {
933  auto *aggregate = dyn_cast<llvm::ConstantAggregate>(operand);
934  if (!aggregate || aggregate->getNumOperands() != 3)
935  return failure();
936 
937  auto *priority = dyn_cast<llvm::ConstantInt>(aggregate->getOperand(0));
938  auto *func = dyn_cast<llvm::Function>(aggregate->getOperand(1));
939  auto *data = dyn_cast<llvm::Constant>(aggregate->getOperand(2));
940  if (!priority || !func || !data)
941  return failure();
942 
943  // GlobalCtorsOps and GlobalDtorsOps do not support non-null data fields.
944  if (!data->isNullValue())
945  return failure();
946 
947  funcs.push_back(FlatSymbolRefAttr::get(context, func->getName()));
948  priorities.push_back(priority->getValue().getZExtValue());
949  }
950 
951  OpBuilder::InsertionGuard guard(builder);
952  if (!globalInsertionOp)
953  builder.setInsertionPointToStart(mlirModule.getBody());
954  else
955  builder.setInsertionPointAfter(globalInsertionOp);
956 
957  if (globalVar->getName() == getGlobalCtorsVarName()) {
958  globalInsertionOp = builder.create<LLVM::GlobalCtorsOp>(
959  mlirModule.getLoc(), builder.getArrayAttr(funcs),
960  builder.getI32ArrayAttr(priorities));
961  return success();
962  }
963  globalInsertionOp = builder.create<LLVM::GlobalDtorsOp>(
964  mlirModule.getLoc(), builder.getArrayAttr(funcs),
965  builder.getI32ArrayAttr(priorities));
966  return success();
967 }
968 
970 ModuleImport::getConstantsToConvert(llvm::Constant *constant) {
971  // Return the empty set if the constant has been translated before.
972  if (valueMapping.contains(constant))
973  return {};
974 
975  // Traverse the constants in post-order and stop the traversal if a constant
976  // already has a `valueMapping` from an earlier constant translation or if the
977  // constant is traversed a second time.
978  SetVector<llvm::Constant *> orderedSet;
981  workList.insert(constant);
982  while (!workList.empty()) {
983  llvm::Constant *current = workList.back();
984  // Collect all dependencies of the current constant and add them to the
985  // adjacency list if none has been computed before.
986  auto adjacencyIt = adjacencyLists.find(current);
987  if (adjacencyIt == adjacencyLists.end()) {
988  adjacencyIt = adjacencyLists.try_emplace(current).first;
989  // Add all constant operands to the adjacency list and skip any other
990  // values such as basic block addresses.
991  for (llvm::Value *operand : current->operands())
992  if (auto *constDependency = dyn_cast<llvm::Constant>(operand))
993  adjacencyIt->getSecond().push_back(constDependency);
994  // Use the getElementValue method to add the dependencies of zero
995  // initialized aggregate constants since they do not take any operands.
996  if (auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(current)) {
997  unsigned numElements = constAgg->getElementCount().getFixedValue();
998  for (unsigned i = 0, e = numElements; i != e; ++i)
999  adjacencyIt->getSecond().push_back(constAgg->getElementValue(i));
1000  }
1001  }
1002  // Add the current constant to the `orderedSet` of the traversed nodes if
1003  // all its dependencies have been traversed before. Additionally, remove the
1004  // constant from the `workList` and continue the traversal.
1005  if (adjacencyIt->getSecond().empty()) {
1006  orderedSet.insert(current);
1007  workList.pop_back();
1008  continue;
1009  }
1010  // Add the next dependency from the adjacency list to the `workList` and
1011  // continue the traversal. Remove the dependency from the adjacency list to
1012  // mark that it has been processed. Only enqueue the dependency if it has no
1013  // `valueMapping` from an earlier translation and if it has not been
1014  // enqueued before.
1015  llvm::Constant *dependency = adjacencyIt->getSecond().pop_back_val();
1016  if (valueMapping.contains(dependency) || workList.contains(dependency) ||
1017  orderedSet.contains(dependency))
1018  continue;
1019  workList.insert(dependency);
1020  }
1021 
1022  return orderedSet;
1023 }
1024 
1025 FailureOr<Value> ModuleImport::convertConstant(llvm::Constant *constant) {
1026  Location loc = UnknownLoc::get(context);
1027 
1028  // Convert constants that can be represented as attributes.
1029  if (Attribute attr = getConstantAsAttr(constant)) {
1030  Type type = convertType(constant->getType());
1031  if (auto symbolRef = dyn_cast<FlatSymbolRefAttr>(attr)) {
1032  return builder.create<AddressOfOp>(loc, type, symbolRef.getValue())
1033  .getResult();
1034  }
1035  return builder.create<ConstantOp>(loc, type, attr).getResult();
1036  }
1037 
1038  // Convert null pointer constants.
1039  if (auto *nullPtr = dyn_cast<llvm::ConstantPointerNull>(constant)) {
1040  Type type = convertType(nullPtr->getType());
1041  return builder.create<ZeroOp>(loc, type).getResult();
1042  }
1043 
1044  // Convert none token constants.
1045  if (isa<llvm::ConstantTokenNone>(constant)) {
1046  return builder.create<NoneTokenOp>(loc).getResult();
1047  }
1048 
1049  // Convert poison.
1050  if (auto *poisonVal = dyn_cast<llvm::PoisonValue>(constant)) {
1051  Type type = convertType(poisonVal->getType());
1052  return builder.create<PoisonOp>(loc, type).getResult();
1053  }
1054 
1055  // Convert undef.
1056  if (auto *undefVal = dyn_cast<llvm::UndefValue>(constant)) {
1057  Type type = convertType(undefVal->getType());
1058  return builder.create<UndefOp>(loc, type).getResult();
1059  }
1060 
1061  // Convert global variable accesses.
1062  if (auto *globalVar = dyn_cast<llvm::GlobalVariable>(constant)) {
1063  Type type = convertType(globalVar->getType());
1064  auto symbolRef = FlatSymbolRefAttr::get(context, globalVar->getName());
1065  return builder.create<AddressOfOp>(loc, type, symbolRef).getResult();
1066  }
1067 
1068  // Convert constant expressions.
1069  if (auto *constExpr = dyn_cast<llvm::ConstantExpr>(constant)) {
1070  // Convert the constant expression to a temporary LLVM instruction and
1071  // translate it using the `processInstruction` method. Delete the
1072  // instruction after the translation and remove it from `valueMapping`,
1073  // since later calls to `getAsInstruction` may return the same address
1074  // resulting in a conflicting `valueMapping` entry.
1075  llvm::Instruction *inst = constExpr->getAsInstruction();
1076  auto guard = llvm::make_scope_exit([&]() {
1077  assert(!noResultOpMapping.contains(inst) &&
1078  "expected constant expression to return a result");
1079  valueMapping.erase(inst);
1080  inst->deleteValue();
1081  });
1082  // Note: `processInstruction` does not call `convertConstant` recursively
1083  // since all constant dependencies have been converted before.
1084  assert(llvm::all_of(inst->operands(), [&](llvm::Value *value) {
1085  return valueMapping.contains(value);
1086  }));
1087  if (failed(processInstruction(inst)))
1088  return failure();
1089  return lookupValue(inst);
1090  }
1091 
1092  // Convert aggregate constants.
1093  if (isa<llvm::ConstantAggregate>(constant) ||
1094  isa<llvm::ConstantAggregateZero>(constant)) {
1095  // Lookup the aggregate elements that have been converted before.
1096  SmallVector<Value> elementValues;
1097  if (auto *constAgg = dyn_cast<llvm::ConstantAggregate>(constant)) {
1098  elementValues.reserve(constAgg->getNumOperands());
1099  for (llvm::Value *operand : constAgg->operands())
1100  elementValues.push_back(lookupValue(operand));
1101  }
1102  if (auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1103  unsigned numElements = constAgg->getElementCount().getFixedValue();
1104  elementValues.reserve(numElements);
1105  for (unsigned i = 0, e = numElements; i != e; ++i)
1106  elementValues.push_back(lookupValue(constAgg->getElementValue(i)));
1107  }
1108  assert(llvm::count(elementValues, nullptr) == 0 &&
1109  "expected all elements have been converted before");
1110 
1111  // Generate an UndefOp as root value and insert the aggregate elements.
1112  Type rootType = convertType(constant->getType());
1113  bool isArrayOrStruct = isa<LLVMArrayType, LLVMStructType>(rootType);
1114  assert((isArrayOrStruct || LLVM::isCompatibleVectorType(rootType)) &&
1115  "unrecognized aggregate type");
1116  Value root = builder.create<UndefOp>(loc, rootType);
1117  for (const auto &it : llvm::enumerate(elementValues)) {
1118  if (isArrayOrStruct) {
1119  root = builder.create<InsertValueOp>(loc, root, it.value(), it.index());
1120  } else {
1121  Attribute indexAttr = builder.getI32IntegerAttr(it.index());
1122  Value indexValue =
1123  builder.create<ConstantOp>(loc, builder.getI32Type(), indexAttr);
1124  root = builder.create<InsertElementOp>(loc, rootType, root, it.value(),
1125  indexValue);
1126  }
1127  }
1128  return root;
1129  }
1130 
1131  if (auto *constTargetNone = dyn_cast<llvm::ConstantTargetNone>(constant)) {
1132  LLVMTargetExtType targetExtType =
1133  cast<LLVMTargetExtType>(convertType(constTargetNone->getType()));
1134  assert(targetExtType.hasProperty(LLVMTargetExtType::HasZeroInit) &&
1135  "target extension type does not support zero-initialization");
1136  // Create llvm.mlir.zero operation to represent zero-initialization of
1137  // target extension type.
1138  return builder.create<LLVM::ZeroOp>(loc, targetExtType).getRes();
1139  }
1140 
1141  StringRef error = "";
1142  if (isa<llvm::BlockAddress>(constant))
1143  error = " since blockaddress(...) is unsupported";
1144 
1145  return emitError(loc) << "unhandled constant: " << diag(*constant) << error;
1146 }
1147 
1148 FailureOr<Value> ModuleImport::convertConstantExpr(llvm::Constant *constant) {
1149  // Only call the function for constants that have not been translated before
1150  // since it updates the constant insertion point assuming the converted
1151  // constant has been introduced at the end of the constant section.
1152  assert(!valueMapping.contains(constant) &&
1153  "expected constant has not been converted before");
1154  assert(constantInsertionBlock &&
1155  "expected the constant insertion block to be non-null");
1156 
1157  // Insert the constant after the last one or at the start of the entry block.
1158  OpBuilder::InsertionGuard guard(builder);
1159  if (!constantInsertionOp)
1160  builder.setInsertionPointToStart(constantInsertionBlock);
1161  else
1162  builder.setInsertionPointAfter(constantInsertionOp);
1163 
1164  // Convert all constants of the expression and add them to `valueMapping`.
1165  SetVector<llvm::Constant *> constantsToConvert =
1166  getConstantsToConvert(constant);
1167  for (llvm::Constant *constantToConvert : constantsToConvert) {
1168  FailureOr<Value> converted = convertConstant(constantToConvert);
1169  if (failed(converted))
1170  return failure();
1171  mapValue(constantToConvert, *converted);
1172  }
1173 
1174  // Update the constant insertion point and return the converted constant.
1175  Value result = lookupValue(constant);
1176  constantInsertionOp = result.getDefiningOp();
1177  return result;
1178 }
1179 
1181  assert(!isa<llvm::MetadataAsValue>(value) &&
1182  "expected value to not be metadata");
1183 
1184  // Return the mapped value if it has been converted before.
1185  auto it = valueMapping.find(value);
1186  if (it != valueMapping.end())
1187  return it->getSecond();
1188 
1189  // Convert constants such as immediate values that have no mapping yet.
1190  if (auto *constant = dyn_cast<llvm::Constant>(value))
1191  return convertConstantExpr(constant);
1192 
1193  Location loc = UnknownLoc::get(context);
1194  if (auto *inst = dyn_cast<llvm::Instruction>(value))
1195  loc = translateLoc(inst->getDebugLoc());
1196  return emitError(loc) << "unhandled value: " << diag(*value);
1197 }
1198 
1200  // A value may be wrapped as metadata, for example, when passed to a debug
1201  // intrinsic. Unwrap these values before the conversion.
1202  auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
1203  if (!nodeAsVal)
1204  return failure();
1205  auto *node = dyn_cast<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
1206  if (!node)
1207  return failure();
1208  value = node->getValue();
1209 
1210  // Return the mapped value if it has been converted before.
1211  auto it = valueMapping.find(value);
1212  if (it != valueMapping.end())
1213  return it->getSecond();
1214 
1215  // Convert constants such as immediate values that have no mapping yet.
1216  if (auto *constant = dyn_cast<llvm::Constant>(value))
1217  return convertConstantExpr(constant);
1218  return failure();
1219 }
1220 
1223  SmallVector<Value> remapped;
1224  remapped.reserve(values.size());
1225  for (llvm::Value *value : values) {
1226  FailureOr<Value> converted = convertValue(value);
1227  if (failed(converted))
1228  return failure();
1229  remapped.push_back(*converted);
1230  }
1231  return remapped;
1232 }
1233 
1235  ArrayRef<llvm::Value *> values, ArrayRef<unsigned> immArgPositions,
1236  ArrayRef<StringLiteral> immArgAttrNames, SmallVectorImpl<Value> &valuesOut,
1237  SmallVectorImpl<NamedAttribute> &attrsOut) {
1238  assert(immArgPositions.size() == immArgAttrNames.size() &&
1239  "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "
1240  "length");
1241 
1242  SmallVector<llvm::Value *> operands(values);
1243  for (auto [immArgPos, immArgName] :
1244  llvm::zip(immArgPositions, immArgAttrNames)) {
1245  auto &value = operands[immArgPos];
1246  auto *constant = llvm::cast<llvm::Constant>(value);
1247  auto attr = getScalarConstantAsAttr(builder, constant);
1248  assert(attr && attr.getType().isIntOrFloat() &&
1249  "expected immarg to be float or integer constant");
1250  auto nameAttr = StringAttr::get(attr.getContext(), immArgName);
1251  attrsOut.push_back({nameAttr, attr});
1252  // Mark matched attribute values as null (so they can be removed below).
1253  value = nullptr;
1254  }
1255 
1256  for (llvm::Value *value : operands) {
1257  if (!value)
1258  continue;
1259  auto mlirValue = convertValue(value);
1260  if (failed(mlirValue))
1261  return failure();
1262  valuesOut.push_back(*mlirValue);
1263  }
1264 
1265  return success();
1266 }
1267 
1268 IntegerAttr ModuleImport::matchIntegerAttr(llvm::Value *value) {
1269  IntegerAttr integerAttr;
1270  FailureOr<Value> converted = convertValue(value);
1271  bool success = succeeded(converted) &&
1272  matchPattern(*converted, m_Constant(&integerAttr));
1273  assert(success && "expected a constant integer value");
1274  (void)success;
1275  return integerAttr;
1276 }
1277 
1278 FloatAttr ModuleImport::matchFloatAttr(llvm::Value *value) {
1279  FloatAttr floatAttr;
1280  FailureOr<Value> converted = convertValue(value);
1281  bool success =
1282  succeeded(converted) && matchPattern(*converted, m_Constant(&floatAttr));
1283  assert(success && "expected a constant float value");
1284  (void)success;
1285  return floatAttr;
1286 }
1287 
1288 DILocalVariableAttr ModuleImport::matchLocalVariableAttr(llvm::Value *value) {
1289  auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
1290  auto *node = cast<llvm::DILocalVariable>(nodeAsVal->getMetadata());
1291  return debugImporter->translate(node);
1292 }
1293 
1294 DILabelAttr ModuleImport::matchLabelAttr(llvm::Value *value) {
1295  auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
1296  auto *node = cast<llvm::DILabel>(nodeAsVal->getMetadata());
1297  return debugImporter->translate(node);
1298 }
1299 
1300 FPExceptionBehaviorAttr
1302  auto *metadata = cast<llvm::MetadataAsValue>(value);
1303  auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
1304  std::optional<llvm::fp::ExceptionBehavior> optLLVM =
1305  llvm::convertStrToExceptionBehavior(mdstr->getString());
1306  assert(optLLVM && "Expecting FP exception behavior");
1307  return builder.getAttr<FPExceptionBehaviorAttr>(
1308  convertFPExceptionBehaviorFromLLVM(*optLLVM));
1309 }
1310 
1311 RoundingModeAttr ModuleImport::matchRoundingModeAttr(llvm::Value *value) {
1312  auto *metadata = cast<llvm::MetadataAsValue>(value);
1313  auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
1314  std::optional<llvm::RoundingMode> optLLVM =
1315  llvm::convertStrToRoundingMode(mdstr->getString());
1316  assert(optLLVM && "Expecting rounding mode");
1317  return builder.getAttr<RoundingModeAttr>(
1318  convertRoundingModeFromLLVM(*optLLVM));
1319 }
1320 
1323  auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
1324  auto *node = cast<llvm::MDNode>(nodeAsVal->getMetadata());
1325  return lookupAliasScopeAttrs(node);
1326 }
1327 
1328 Location ModuleImport::translateLoc(llvm::DILocation *loc) {
1329  return debugImporter->translateLoc(loc);
1330 }
1331 
1333 ModuleImport::convertBranchArgs(llvm::Instruction *branch,
1334  llvm::BasicBlock *target,
1335  SmallVectorImpl<Value> &blockArguments) {
1336  for (auto inst = target->begin(); isa<llvm::PHINode>(inst); ++inst) {
1337  auto *phiInst = cast<llvm::PHINode>(&*inst);
1338  llvm::Value *value = phiInst->getIncomingValueForBlock(branch->getParent());
1339  FailureOr<Value> converted = convertValue(value);
1340  if (failed(converted))
1341  return failure();
1342  blockArguments.push_back(*converted);
1343  }
1344  return success();
1345 }
1346 
1348 ModuleImport::convertCallTypeAndOperands(llvm::CallBase *callInst,
1349  SmallVectorImpl<Type> &types,
1350  SmallVectorImpl<Value> &operands) {
1351  if (!callInst->getType()->isVoidTy())
1352  types.push_back(convertType(callInst->getType()));
1353 
1354  if (!callInst->getCalledFunction()) {
1355  FailureOr<Value> called = convertValue(callInst->getCalledOperand());
1356  if (failed(called))
1357  return failure();
1358  operands.push_back(*called);
1359  }
1360  SmallVector<llvm::Value *> args(callInst->args());
1361  FailureOr<SmallVector<Value>> arguments = convertValues(args);
1362  if (failed(arguments))
1363  return failure();
1364  llvm::append_range(operands, *arguments);
1365  return success();
1366 }
1367 
1368 LogicalResult ModuleImport::convertIntrinsic(llvm::CallInst *inst) {
1369  if (succeeded(iface.convertIntrinsic(builder, inst, *this)))
1370  return success();
1371 
1372  Location loc = translateLoc(inst->getDebugLoc());
1373  return emitError(loc) << "unhandled intrinsic: " << diag(*inst);
1374 }
1375 
1376 LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
1377  // Convert all instructions that do not provide an MLIR builder.
1378  Location loc = translateLoc(inst->getDebugLoc());
1379  if (inst->getOpcode() == llvm::Instruction::Br) {
1380  auto *brInst = cast<llvm::BranchInst>(inst);
1381 
1382  SmallVector<Block *> succBlocks;
1383  SmallVector<SmallVector<Value>> succBlockArgs;
1384  for (auto i : llvm::seq<unsigned>(0, brInst->getNumSuccessors())) {
1385  llvm::BasicBlock *succ = brInst->getSuccessor(i);
1386  SmallVector<Value> blockArgs;
1387  if (failed(convertBranchArgs(brInst, succ, blockArgs)))
1388  return failure();
1389  succBlocks.push_back(lookupBlock(succ));
1390  succBlockArgs.push_back(blockArgs);
1391  }
1392 
1393  if (!brInst->isConditional()) {
1394  auto brOp = builder.create<LLVM::BrOp>(loc, succBlockArgs.front(),
1395  succBlocks.front());
1396  mapNoResultOp(inst, brOp);
1397  return success();
1398  }
1399  FailureOr<Value> condition = convertValue(brInst->getCondition());
1400  if (failed(condition))
1401  return failure();
1402  auto condBrOp = builder.create<LLVM::CondBrOp>(
1403  loc, *condition, succBlocks.front(), succBlockArgs.front(),
1404  succBlocks.back(), succBlockArgs.back());
1405  mapNoResultOp(inst, condBrOp);
1406  return success();
1407  }
1408  if (inst->getOpcode() == llvm::Instruction::Switch) {
1409  auto *swInst = cast<llvm::SwitchInst>(inst);
1410  // Process the condition value.
1411  FailureOr<Value> condition = convertValue(swInst->getCondition());
1412  if (failed(condition))
1413  return failure();
1414  SmallVector<Value> defaultBlockArgs;
1415  // Process the default case.
1416  llvm::BasicBlock *defaultBB = swInst->getDefaultDest();
1417  if (failed(convertBranchArgs(swInst, defaultBB, defaultBlockArgs)))
1418  return failure();
1419 
1420  // Process the cases.
1421  unsigned numCases = swInst->getNumCases();
1422  SmallVector<SmallVector<Value>> caseOperands(numCases);
1423  SmallVector<ValueRange> caseOperandRefs(numCases);
1424  SmallVector<APInt> caseValues(numCases);
1425  SmallVector<Block *> caseBlocks(numCases);
1426  for (const auto &it : llvm::enumerate(swInst->cases())) {
1427  const llvm::SwitchInst::CaseHandle &caseHandle = it.value();
1428  llvm::BasicBlock *succBB = caseHandle.getCaseSuccessor();
1429  if (failed(convertBranchArgs(swInst, succBB, caseOperands[it.index()])))
1430  return failure();
1431  caseOperandRefs[it.index()] = caseOperands[it.index()];
1432  caseValues[it.index()] = caseHandle.getCaseValue()->getValue();
1433  caseBlocks[it.index()] = lookupBlock(succBB);
1434  }
1435 
1436  auto switchOp = builder.create<SwitchOp>(
1437  loc, *condition, lookupBlock(defaultBB), defaultBlockArgs, caseValues,
1438  caseBlocks, caseOperandRefs);
1439  mapNoResultOp(inst, switchOp);
1440  return success();
1441  }
1442  if (inst->getOpcode() == llvm::Instruction::PHI) {
1443  Type type = convertType(inst->getType());
1444  mapValue(inst, builder.getInsertionBlock()->addArgument(
1445  type, translateLoc(inst->getDebugLoc())));
1446  return success();
1447  }
1448  if (inst->getOpcode() == llvm::Instruction::Call) {
1449  auto *callInst = cast<llvm::CallInst>(inst);
1450 
1451  SmallVector<Type> types;
1452  SmallVector<Value> operands;
1453  if (failed(convertCallTypeAndOperands(callInst, types, operands)))
1454  return failure();
1455 
1456  auto funcTy =
1457  dyn_cast<LLVMFunctionType>(convertType(callInst->getFunctionType()));
1458  if (!funcTy)
1459  return failure();
1460 
1461  CallOp callOp;
1462 
1463  if (llvm::Function *callee = callInst->getCalledFunction()) {
1464  callOp = builder.create<CallOp>(
1465  loc, funcTy, SymbolRefAttr::get(context, callee->getName()),
1466  operands);
1467  } else {
1468  callOp = builder.create<CallOp>(loc, funcTy, operands);
1469  }
1470  callOp.setCConv(convertCConvFromLLVM(callInst->getCallingConv()));
1471  setFastmathFlagsAttr(inst, callOp);
1472  if (!callInst->getType()->isVoidTy())
1473  mapValue(inst, callOp.getResult());
1474  else
1475  mapNoResultOp(inst, callOp);
1476  return success();
1477  }
1478  if (inst->getOpcode() == llvm::Instruction::LandingPad) {
1479  auto *lpInst = cast<llvm::LandingPadInst>(inst);
1480 
1481  SmallVector<Value> operands;
1482  operands.reserve(lpInst->getNumClauses());
1483  for (auto i : llvm::seq<unsigned>(0, lpInst->getNumClauses())) {
1484  FailureOr<Value> operand = convertValue(lpInst->getClause(i));
1485  if (failed(operand))
1486  return failure();
1487  operands.push_back(*operand);
1488  }
1489 
1490  Type type = convertType(lpInst->getType());
1491  auto lpOp =
1492  builder.create<LandingpadOp>(loc, type, lpInst->isCleanup(), operands);
1493  mapValue(inst, lpOp);
1494  return success();
1495  }
1496  if (inst->getOpcode() == llvm::Instruction::Invoke) {
1497  auto *invokeInst = cast<llvm::InvokeInst>(inst);
1498 
1499  SmallVector<Type> types;
1500  SmallVector<Value> operands;
1501  if (failed(convertCallTypeAndOperands(invokeInst, types, operands)))
1502  return failure();
1503 
1504  // Check whether the invoke result is an argument to the normal destination
1505  // block.
1506  bool invokeResultUsedInPhi = llvm::any_of(
1507  invokeInst->getNormalDest()->phis(), [&](const llvm::PHINode &phi) {
1508  return phi.getIncomingValueForBlock(invokeInst->getParent()) ==
1509  invokeInst;
1510  });
1511 
1512  Block *normalDest = lookupBlock(invokeInst->getNormalDest());
1513  Block *directNormalDest = normalDest;
1514  if (invokeResultUsedInPhi) {
1515  // The invoke result cannot be an argument to the normal destination
1516  // block, as that would imply using the invoke operation result in its
1517  // definition, so we need to create a dummy block to serve as an
1518  // intermediate destination.
1519  OpBuilder::InsertionGuard g(builder);
1520  directNormalDest = builder.createBlock(normalDest);
1521  }
1522 
1523  SmallVector<Value> unwindArgs;
1524  if (failed(convertBranchArgs(invokeInst, invokeInst->getUnwindDest(),
1525  unwindArgs)))
1526  return failure();
1527 
1528  auto funcTy =
1529  dyn_cast<LLVMFunctionType>(convertType(invokeInst->getFunctionType()));
1530  if (!funcTy)
1531  return failure();
1532 
1533  // Create the invoke operation. Normal destination block arguments will be
1534  // added later on to handle the case in which the operation result is
1535  // included in this list.
1536  InvokeOp invokeOp;
1537  if (llvm::Function *callee = invokeInst->getCalledFunction()) {
1538  invokeOp = builder.create<InvokeOp>(
1539  loc, funcTy,
1540  SymbolRefAttr::get(builder.getContext(), callee->getName()), operands,
1541  directNormalDest, ValueRange(),
1542  lookupBlock(invokeInst->getUnwindDest()), unwindArgs);
1543  } else {
1544  invokeOp = builder.create<InvokeOp>(
1545  loc, funcTy, /*callee=*/nullptr, operands, directNormalDest,
1546  ValueRange(), lookupBlock(invokeInst->getUnwindDest()), unwindArgs);
1547  }
1548  invokeOp.setCConv(convertCConvFromLLVM(invokeInst->getCallingConv()));
1549  if (!invokeInst->getType()->isVoidTy())
1550  mapValue(inst, invokeOp.getResults().front());
1551  else
1552  mapNoResultOp(inst, invokeOp);
1553 
1554  SmallVector<Value> normalArgs;
1555  if (failed(convertBranchArgs(invokeInst, invokeInst->getNormalDest(),
1556  normalArgs)))
1557  return failure();
1558 
1559  if (invokeResultUsedInPhi) {
1560  // The dummy normal dest block will just host an unconditional branch
1561  // instruction to the normal destination block passing the required block
1562  // arguments (including the invoke operation's result).
1563  OpBuilder::InsertionGuard g(builder);
1564  builder.setInsertionPointToStart(directNormalDest);
1565  builder.create<LLVM::BrOp>(loc, normalArgs, normalDest);
1566  } else {
1567  // If the invoke operation's result is not a block argument to the normal
1568  // destination block, just add the block arguments as usual.
1569  assert(llvm::none_of(
1570  normalArgs,
1571  [&](Value val) { return val.getDefiningOp() == invokeOp; }) &&
1572  "An llvm.invoke operation cannot pass its result as a block "
1573  "argument.");
1574  invokeOp.getNormalDestOperandsMutable().append(normalArgs);
1575  }
1576 
1577  return success();
1578  }
1579  if (inst->getOpcode() == llvm::Instruction::GetElementPtr) {
1580  auto *gepInst = cast<llvm::GetElementPtrInst>(inst);
1581  Type sourceElementType = convertType(gepInst->getSourceElementType());
1582  FailureOr<Value> basePtr = convertValue(gepInst->getOperand(0));
1583  if (failed(basePtr))
1584  return failure();
1585 
1586  // Treat every indices as dynamic since GEPOp::build will refine those
1587  // indices into static attributes later. One small downside of this
1588  // approach is that many unused `llvm.mlir.constant` would be emitted
1589  // at first place.
1590  SmallVector<GEPArg> indices;
1591  for (llvm::Value *operand : llvm::drop_begin(gepInst->operand_values())) {
1592  FailureOr<Value> index = convertValue(operand);
1593  if (failed(index))
1594  return failure();
1595  indices.push_back(*index);
1596  }
1597 
1598  Type type = convertType(inst->getType());
1599  auto gepOp = builder.create<GEPOp>(loc, type, sourceElementType, *basePtr,
1600  indices, gepInst->isInBounds());
1601  mapValue(inst, gepOp);
1602  return success();
1603  }
1604 
1605  // Convert all instructions that have an mlirBuilder.
1606  if (succeeded(convertInstructionImpl(builder, inst, *this, iface)))
1607  return success();
1608 
1609  return emitError(loc) << "unhandled instruction: " << diag(*inst);
1610 }
1611 
1612 LogicalResult ModuleImport::processInstruction(llvm::Instruction *inst) {
1613  // FIXME: Support uses of SubtargetData.
1614  // FIXME: Add support for call / operand attributes.
1615  // FIXME: Add support for the indirectbr, cleanupret, catchret, catchswitch,
1616  // callbr, vaarg, catchpad, cleanuppad instructions.
1617 
1618  // Convert LLVM intrinsics calls to MLIR intrinsics.
1619  if (auto *intrinsic = dyn_cast<llvm::IntrinsicInst>(inst))
1620  return convertIntrinsic(intrinsic);
1621 
1622  // Convert all remaining LLVM instructions to MLIR operations.
1623  return convertInstruction(inst);
1624 }
1625 
1626 FlatSymbolRefAttr ModuleImport::getPersonalityAsAttr(llvm::Function *f) {
1627  if (!f->hasPersonalityFn())
1628  return nullptr;
1629 
1630  llvm::Constant *pf = f->getPersonalityFn();
1631 
1632  // If it directly has a name, we can use it.
1633  if (pf->hasName())
1634  return SymbolRefAttr::get(builder.getContext(), pf->getName());
1635 
1636  // If it doesn't have a name, currently, only function pointers that are
1637  // bitcast to i8* are parsed.
1638  if (auto *ce = dyn_cast<llvm::ConstantExpr>(pf)) {
1639  if (ce->getOpcode() == llvm::Instruction::BitCast &&
1640  ce->getType() == llvm::PointerType::getUnqual(f->getContext())) {
1641  if (auto *func = dyn_cast<llvm::Function>(ce->getOperand(0)))
1642  return SymbolRefAttr::get(builder.getContext(), func->getName());
1643  }
1644  }
1645  return FlatSymbolRefAttr();
1646 }
1647 
1648 static void processMemoryEffects(llvm::Function *func, LLVMFuncOp funcOp) {
1649  llvm::MemoryEffects memEffects = func->getMemoryEffects();
1650 
1651  auto othermem = convertModRefInfoFromLLVM(
1652  memEffects.getModRef(llvm::MemoryEffects::Location::Other));
1653  auto argMem = convertModRefInfoFromLLVM(
1654  memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
1655  auto inaccessibleMem = convertModRefInfoFromLLVM(
1656  memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
1657  auto memAttr = MemoryEffectsAttr::get(funcOp.getContext(), othermem, argMem,
1658  inaccessibleMem);
1659  // Only set the attr when it does not match the default value.
1660  if (memAttr.isReadWrite())
1661  return;
1662  funcOp.setMemoryAttr(memAttr);
1663 }
1664 
1665 // List of LLVM IR attributes that map to an explicit attribute on the MLIR
1666 // LLVMFuncOp.
1667 static constexpr std::array kExplicitAttributes{
1668  StringLiteral("aarch64_in_za"),
1669  StringLiteral("aarch64_inout_za"),
1670  StringLiteral("aarch64_new_za"),
1671  StringLiteral("aarch64_out_za"),
1672  StringLiteral("aarch64_preserves_za"),
1673  StringLiteral("aarch64_pstate_sm_body"),
1674  StringLiteral("aarch64_pstate_sm_compatible"),
1675  StringLiteral("aarch64_pstate_sm_enabled"),
1676  StringLiteral("alwaysinline"),
1677  StringLiteral("approx-func-fp-math"),
1678  StringLiteral("frame-pointer"),
1679  StringLiteral("no-infs-fp-math"),
1680  StringLiteral("no-nans-fp-math"),
1681  StringLiteral("no-signed-zeros-fp-math"),
1682  StringLiteral("noinline"),
1683  StringLiteral("optnone"),
1684  StringLiteral("target-features"),
1685  StringLiteral("unsafe-fp-math"),
1686  StringLiteral("vscale_range"),
1687 };
1688 
1689 static void processPassthroughAttrs(llvm::Function *func, LLVMFuncOp funcOp) {
1690  MLIRContext *context = funcOp.getContext();
1691  SmallVector<Attribute> passthroughs;
1692  llvm::AttributeSet funcAttrs = func->getAttributes().getAttributes(
1693  llvm::AttributeList::AttrIndex::FunctionIndex);
1694  for (llvm::Attribute attr : funcAttrs) {
1695  // Skip the memory attribute since the LLVMFuncOp has an explicit memory
1696  // attribute.
1697  if (attr.hasAttribute(llvm::Attribute::Memory))
1698  continue;
1699 
1700  // Skip invalid type attributes.
1701  if (attr.isTypeAttribute()) {
1702  emitWarning(funcOp.getLoc(),
1703  "type attributes on a function are invalid, skipping it");
1704  continue;
1705  }
1706 
1707  StringRef attrName;
1708  if (attr.isStringAttribute())
1709  attrName = attr.getKindAsString();
1710  else
1711  attrName = llvm::Attribute::getNameFromAttrKind(attr.getKindAsEnum());
1712  auto keyAttr = StringAttr::get(context, attrName);
1713 
1714  // Skip attributes that map to an explicit attribute on the LLVMFuncOp.
1715  if (llvm::is_contained(kExplicitAttributes, attrName))
1716  continue;
1717 
1718  if (attr.isStringAttribute()) {
1719  StringRef val = attr.getValueAsString();
1720  if (val.empty()) {
1721  passthroughs.push_back(keyAttr);
1722  continue;
1723  }
1724  passthroughs.push_back(
1725  ArrayAttr::get(context, {keyAttr, StringAttr::get(context, val)}));
1726  continue;
1727  }
1728  if (attr.isIntAttribute()) {
1729  auto val = std::to_string(attr.getValueAsInt());
1730  passthroughs.push_back(
1731  ArrayAttr::get(context, {keyAttr, StringAttr::get(context, val)}));
1732  continue;
1733  }
1734  if (attr.isEnumAttribute()) {
1735  passthroughs.push_back(keyAttr);
1736  continue;
1737  }
1738 
1739  llvm_unreachable("unexpected attribute kind");
1740  }
1741 
1742  if (!passthroughs.empty())
1743  funcOp.setPassthroughAttr(ArrayAttr::get(context, passthroughs));
1744 }
1745 
1747  LLVMFuncOp funcOp) {
1748  processMemoryEffects(func, funcOp);
1749  processPassthroughAttrs(func, funcOp);
1750 
1751  if (func->hasFnAttribute(llvm::Attribute::NoInline))
1752  funcOp.setNoInline(true);
1753  if (func->hasFnAttribute(llvm::Attribute::AlwaysInline))
1754  funcOp.setAlwaysInline(true);
1755  if (func->hasFnAttribute(llvm::Attribute::OptimizeNone))
1756  funcOp.setOptimizeNone(true);
1757 
1758  if (func->hasFnAttribute("aarch64_pstate_sm_enabled"))
1759  funcOp.setArmStreaming(true);
1760  else if (func->hasFnAttribute("aarch64_pstate_sm_body"))
1761  funcOp.setArmLocallyStreaming(true);
1762  else if (func->hasFnAttribute("aarch64_pstate_sm_compatible"))
1763  funcOp.setArmStreamingCompatible(true);
1764 
1765  if (func->hasFnAttribute("aarch64_new_za"))
1766  funcOp.setArmNewZa(true);
1767  else if (func->hasFnAttribute("aarch64_in_za"))
1768  funcOp.setArmInZa(true);
1769  else if (func->hasFnAttribute("aarch64_out_za"))
1770  funcOp.setArmOutZa(true);
1771  else if (func->hasFnAttribute("aarch64_inout_za"))
1772  funcOp.setArmInoutZa(true);
1773  else if (func->hasFnAttribute("aarch64_preserves_za"))
1774  funcOp.setArmPreservesZa(true);
1775 
1776  llvm::Attribute attr = func->getFnAttribute(llvm::Attribute::VScaleRange);
1777  if (attr.isValid()) {
1778  MLIRContext *context = funcOp.getContext();
1779  auto intTy = IntegerType::get(context, 32);
1780  funcOp.setVscaleRangeAttr(LLVM::VScaleRangeAttr::get(
1781  context, IntegerAttr::get(intTy, attr.getVScaleRangeMin()),
1782  IntegerAttr::get(intTy, attr.getVScaleRangeMax().value_or(0))));
1783  }
1784 
1785  // Process frame-pointer attribute.
1786  if (func->hasFnAttribute("frame-pointer")) {
1787  StringRef stringRefFramePointerKind =
1788  func->getFnAttribute("frame-pointer").getValueAsString();
1789  funcOp.setFramePointerAttr(LLVM::FramePointerKindAttr::get(
1790  funcOp.getContext(), LLVM::framePointerKind::symbolizeFramePointerKind(
1791  stringRefFramePointerKind)
1792  .value()));
1793  }
1794 
1795  if (llvm::Attribute attr = func->getFnAttribute("target-cpu");
1796  attr.isStringAttribute())
1797  funcOp.setTargetCpuAttr(StringAttr::get(context, attr.getValueAsString()));
1798 
1799  if (llvm::Attribute attr = func->getFnAttribute("target-features");
1800  attr.isStringAttribute())
1801  funcOp.setTargetFeaturesAttr(
1802  LLVM::TargetFeaturesAttr::get(context, attr.getValueAsString()));
1803 
1804  if (llvm::Attribute attr = func->getFnAttribute("unsafe-fp-math");
1805  attr.isStringAttribute())
1806  funcOp.setUnsafeFpMath(attr.getValueAsBool());
1807 
1808  if (llvm::Attribute attr = func->getFnAttribute("no-infs-fp-math");
1809  attr.isStringAttribute())
1810  funcOp.setNoInfsFpMath(attr.getValueAsBool());
1811 
1812  if (llvm::Attribute attr = func->getFnAttribute("no-nans-fp-math");
1813  attr.isStringAttribute())
1814  funcOp.setNoNansFpMath(attr.getValueAsBool());
1815 
1816  if (llvm::Attribute attr = func->getFnAttribute("approx-func-fp-math");
1817  attr.isStringAttribute())
1818  funcOp.setApproxFuncFpMath(attr.getValueAsBool());
1819 
1820  if (llvm::Attribute attr = func->getFnAttribute("no-signed-zeros-fp-math");
1821  attr.isStringAttribute())
1822  funcOp.setNoSignedZerosFpMath(attr.getValueAsBool());
1823 }
1824 
1825 DictionaryAttr
1826 ModuleImport::convertParameterAttribute(llvm::AttributeSet llvmParamAttrs,
1827  OpBuilder &builder) {
1828  SmallVector<NamedAttribute> paramAttrs;
1829  for (auto [llvmKind, mlirName] : getAttrKindToNameMapping()) {
1830  auto llvmAttr = llvmParamAttrs.getAttribute(llvmKind);
1831  // Skip attributes that are not attached.
1832  if (!llvmAttr.isValid())
1833  continue;
1834  Attribute mlirAttr;
1835  if (llvmAttr.isTypeAttribute())
1836  mlirAttr = TypeAttr::get(convertType(llvmAttr.getValueAsType()));
1837  else if (llvmAttr.isIntAttribute())
1838  mlirAttr = builder.getI64IntegerAttr(llvmAttr.getValueAsInt());
1839  else if (llvmAttr.isEnumAttribute())
1840  mlirAttr = builder.getUnitAttr();
1841  else
1842  llvm_unreachable("unexpected parameter attribute kind");
1843  paramAttrs.push_back(builder.getNamedAttr(mlirName, mlirAttr));
1844  }
1845 
1846  return builder.getDictionaryAttr(paramAttrs);
1847 }
1848 
1849 void ModuleImport::convertParameterAttributes(llvm::Function *func,
1850  LLVMFuncOp funcOp,
1851  OpBuilder &builder) {
1852  auto llvmAttrs = func->getAttributes();
1853  for (size_t i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
1854  llvm::AttributeSet llvmArgAttrs = llvmAttrs.getParamAttrs(i);
1855  funcOp.setArgAttrs(i, convertParameterAttribute(llvmArgAttrs, builder));
1856  }
1857  // Convert the result attributes and attach them wrapped in an ArrayAttribute
1858  // to the funcOp.
1859  llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
1860  if (!llvmResAttr.hasAttributes())
1861  return;
1862  funcOp.setResAttrsAttr(
1863  builder.getArrayAttr(convertParameterAttribute(llvmResAttr, builder)));
1864 }
1865 
1867  clearRegionState();
1868 
1869  auto functionType =
1870  dyn_cast<LLVMFunctionType>(convertType(func->getFunctionType()));
1871  if (func->isIntrinsic() &&
1872  iface.isConvertibleIntrinsic(func->getIntrinsicID()))
1873  return success();
1874 
1875  bool dsoLocal = func->hasLocalLinkage();
1876  CConv cconv = convertCConvFromLLVM(func->getCallingConv());
1877 
1878  // Insert the function at the end of the module.
1879  OpBuilder::InsertionGuard guard(builder);
1880  builder.setInsertionPoint(mlirModule.getBody(), mlirModule.getBody()->end());
1881 
1882  Location loc = debugImporter->translateFuncLocation(func);
1883  LLVMFuncOp funcOp = builder.create<LLVMFuncOp>(
1884  loc, func->getName(), functionType,
1885  convertLinkageFromLLVM(func->getLinkage()), dsoLocal, cconv);
1886 
1887  convertParameterAttributes(func, funcOp, builder);
1888 
1889  if (FlatSymbolRefAttr personality = getPersonalityAsAttr(func))
1890  funcOp.setPersonalityAttr(personality);
1891  else if (func->hasPersonalityFn())
1892  emitWarning(funcOp.getLoc(), "could not deduce personality, skipping it");
1893 
1894  if (func->hasGC())
1895  funcOp.setGarbageCollector(StringRef(func->getGC()));
1896 
1897  if (func->hasAtLeastLocalUnnamedAddr())
1898  funcOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(func->getUnnamedAddr()));
1899 
1900  if (func->hasSection())
1901  funcOp.setSection(StringRef(func->getSection()));
1902 
1903  funcOp.setVisibility_(convertVisibilityFromLLVM(func->getVisibility()));
1904 
1905  if (func->hasComdat())
1906  funcOp.setComdatAttr(comdatMapping.lookup(func->getComdat()));
1907 
1908  if (llvm::MaybeAlign maybeAlign = func->getAlign())
1909  funcOp.setAlignment(maybeAlign->value());
1910 
1911  // Handle Function attributes.
1912  processFunctionAttributes(func, funcOp);
1913 
1914  // Convert non-debug metadata by using the dialect interface.
1916  func->getAllMetadata(allMetadata);
1917  for (auto &[kind, node] : allMetadata) {
1918  if (!iface.isConvertibleMetadata(kind))
1919  continue;
1920  if (failed(iface.setMetadataAttrs(builder, kind, node, funcOp, *this))) {
1921  emitWarning(funcOp.getLoc())
1922  << "unhandled function metadata: " << diagMD(node, llvmModule.get())
1923  << " on " << diag(*func);
1924  }
1925  }
1926 
1927  if (func->isDeclaration())
1928  return success();
1929 
1930  // Collect the set of basic blocks reachable from the function's entry block.
1931  // This step is crucial as LLVM IR can contain unreachable blocks that
1932  // self-dominate. As a result, an operation might utilize a variable it
1933  // defines, which the import does not support. Given that MLIR lacks block
1934  // label support, we can safely remove unreachable blocks, as there are no
1935  // indirect branch instructions that could potentially target these blocks.
1936  llvm::df_iterator_default_set<llvm::BasicBlock *> reachable;
1937  for (llvm::BasicBlock *basicBlock : llvm::depth_first_ext(func, reachable))
1938  (void)basicBlock;
1939 
1940  // Eagerly create all reachable blocks.
1941  SmallVector<llvm::BasicBlock *> reachableBasicBlocks;
1942  for (llvm::BasicBlock &basicBlock : *func) {
1943  // Skip unreachable blocks.
1944  if (!reachable.contains(&basicBlock))
1945  continue;
1946  Region &body = funcOp.getBody();
1947  Block *block = builder.createBlock(&body, body.end());
1948  mapBlock(&basicBlock, block);
1949  reachableBasicBlocks.push_back(&basicBlock);
1950  }
1951 
1952  // Add function arguments to the entry block.
1953  for (const auto &it : llvm::enumerate(func->args())) {
1954  BlockArgument blockArg = funcOp.getFunctionBody().addArgument(
1955  functionType.getParamType(it.index()), funcOp.getLoc());
1956  mapValue(&it.value(), blockArg);
1957  }
1958 
1959  // Process the blocks in topological order. The ordered traversal ensures
1960  // operands defined in a dominating block have a valid mapping to an MLIR
1961  // value once a block is translated.
1963  getTopologicallySortedBlocks(reachableBasicBlocks);
1964  setConstantInsertionPointToStart(lookupBlock(blocks.front()));
1965  for (llvm::BasicBlock *basicBlock : blocks)
1966  if (failed(processBasicBlock(basicBlock, lookupBlock(basicBlock))))
1967  return failure();
1968 
1969  // Process the debug intrinsics that require a delayed conversion after
1970  // everything else was converted.
1971  if (failed(processDebugIntrinsics()))
1972  return failure();
1973 
1974  return success();
1975 }
1976 
1977 /// Checks if `dbgIntr` is a kill location that holds metadata instead of an SSA
1978 /// value.
1979 static bool isMetadataKillLocation(llvm::DbgVariableIntrinsic *dbgIntr) {
1980  if (!dbgIntr->isKillLocation())
1981  return false;
1982  llvm::Value *value = dbgIntr->getArgOperand(0);
1983  auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
1984  if (!nodeAsVal)
1985  return false;
1986  return !isa<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
1987 }
1988 
1990 ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr,
1991  DominanceInfo &domInfo) {
1992  Location loc = translateLoc(dbgIntr->getDebugLoc());
1993  auto emitUnsupportedWarning = [&]() {
1994  if (emitExpensiveWarnings)
1995  emitWarning(loc) << "dropped intrinsic: " << diag(*dbgIntr);
1996  return success();
1997  };
1998  // Drop debug intrinsics with arg lists.
1999  // TODO: Support debug intrinsics that have arg lists.
2000  if (dbgIntr->hasArgList())
2001  return emitUnsupportedWarning();
2002  // Kill locations can have metadata nodes as location operand. This
2003  // cannot be converted to poison as the type cannot be reconstructed.
2004  // TODO: find a way to support this case.
2005  if (isMetadataKillLocation(dbgIntr))
2006  return emitUnsupportedWarning();
2007  // Drop debug intrinsics if the associated variable information cannot be
2008  // translated due to cyclic debug metadata.
2009  // TODO: Support cyclic debug metadata.
2010  DILocalVariableAttr localVariableAttr =
2011  matchLocalVariableAttr(dbgIntr->getArgOperand(1));
2012  if (!localVariableAttr)
2013  return emitUnsupportedWarning();
2014  FailureOr<Value> argOperand = convertMetadataValue(dbgIntr->getArgOperand(0));
2015  if (failed(argOperand))
2016  return emitError(loc) << "failed to convert a debug intrinsic operand: "
2017  << diag(*dbgIntr);
2018 
2019  // Ensure that the debug instrinsic is inserted right after its operand is
2020  // defined. Otherwise, the operand might not necessarily dominate the
2021  // intrinsic. If the defining operation is a terminator, insert the intrinsic
2022  // into a dominated block.
2023  OpBuilder::InsertionGuard guard(builder);
2024  if (Operation *op = argOperand->getDefiningOp();
2025  op && op->hasTrait<OpTrait::IsTerminator>()) {
2026  // Find a dominated block that can hold the debug intrinsic.
2027  auto dominatedBlocks = domInfo.getNode(op->getBlock())->children();
2028  // If no block is dominated by the terminator, this intrinisc cannot be
2029  // converted.
2030  if (dominatedBlocks.empty())
2031  return emitUnsupportedWarning();
2032  // Set insertion point before the terminator, to avoid inserting something
2033  // before landingpads.
2034  Block *dominatedBlock = (*dominatedBlocks.begin())->getBlock();
2035  builder.setInsertionPoint(dominatedBlock->getTerminator());
2036  } else {
2037  builder.setInsertionPointAfterValue(*argOperand);
2038  }
2039  auto locationExprAttr =
2040  debugImporter->translateExpression(dbgIntr->getExpression());
2041  Operation *op =
2043  .Case([&](llvm::DbgDeclareInst *) {
2044  return builder.create<LLVM::DbgDeclareOp>(
2045  loc, *argOperand, localVariableAttr, locationExprAttr);
2046  })
2047  .Case([&](llvm::DbgValueInst *) {
2048  return builder.create<LLVM::DbgValueOp>(
2049  loc, *argOperand, localVariableAttr, locationExprAttr);
2050  });
2051  mapNoResultOp(dbgIntr, op);
2052  setNonDebugMetadataAttrs(dbgIntr, op);
2053  return success();
2054 }
2055 
2056 LogicalResult ModuleImport::processDebugIntrinsics() {
2057  DominanceInfo domInfo;
2058  for (llvm::Instruction *inst : debugIntrinsics) {
2059  auto *intrCall = cast<llvm::DbgVariableIntrinsic>(inst);
2060  if (failed(processDebugIntrinsic(intrCall, domInfo)))
2061  return failure();
2062  }
2063  return success();
2064 }
2065 
2066 LogicalResult ModuleImport::processBasicBlock(llvm::BasicBlock *bb,
2067  Block *block) {
2068  builder.setInsertionPointToStart(block);
2069  for (llvm::Instruction &inst : *bb) {
2070  if (failed(processInstruction(&inst)))
2071  return failure();
2072 
2073  // Skip additional processing when the instructions is a debug intrinsics
2074  // that was not yet converted.
2075  if (debugIntrinsics.contains(&inst))
2076  continue;
2077 
2078  // Set the non-debug metadata attributes on the imported operation and emit
2079  // a warning if an instruction other than a phi instruction is dropped
2080  // during the import.
2081  if (Operation *op = lookupOperation(&inst)) {
2082  setNonDebugMetadataAttrs(&inst, op);
2083  } else if (inst.getOpcode() != llvm::Instruction::PHI) {
2084  if (emitExpensiveWarnings) {
2085  Location loc = debugImporter->translateLoc(inst.getDebugLoc());
2086  emitWarning(loc) << "dropped instruction: " << diag(inst);
2087  }
2088  }
2089  }
2090  return success();
2091 }
2092 
2094 ModuleImport::lookupAccessGroupAttrs(const llvm::MDNode *node) const {
2095  return loopAnnotationImporter->lookupAccessGroupAttrs(node);
2096 }
2097 
2098 LoopAnnotationAttr
2100  Location loc) const {
2101  return loopAnnotationImporter->translateLoopAnnotation(node, loc);
2102 }
2103 
2105 mlir::translateLLVMIRToModule(std::unique_ptr<llvm::Module> llvmModule,
2106  MLIRContext *context, bool emitExpensiveWarnings,
2107  bool dropDICompositeTypeElements) {
2108  // Preload all registered dialects to allow the import to iterate the
2109  // registered LLVMImportDialectInterface implementations and query the
2110  // supported LLVM IR constructs before starting the translation. Assumes the
2111  // LLVM and DLTI dialects that convert the core LLVM IR constructs have been
2112  // registered before.
2113  assert(llvm::is_contained(context->getAvailableDialects(),
2114  LLVMDialect::getDialectNamespace()));
2115  assert(llvm::is_contained(context->getAvailableDialects(),
2116  DLTIDialect::getDialectNamespace()));
2117  context->loadAllAvailableDialects();
2118  OwningOpRef<ModuleOp> module(ModuleOp::create(FileLineColLoc::get(
2119  StringAttr::get(context, llvmModule->getSourceFileName()), /*line=*/0,
2120  /*column=*/0)));
2121 
2122  ModuleImport moduleImport(module.get(), std::move(llvmModule),
2123  emitExpensiveWarnings, dropDICompositeTypeElements);
2124  if (failed(moduleImport.initializeImportInterface()))
2125  return {};
2126  if (failed(moduleImport.convertDataLayout()))
2127  return {};
2128  if (failed(moduleImport.convertComdats()))
2129  return {};
2130  if (failed(moduleImport.convertMetadata()))
2131  return {};
2132  if (failed(moduleImport.convertGlobals()))
2133  return {};
2134  if (failed(moduleImport.convertFunctions()))
2135  return {};
2136 
2137  return module;
2138 }
static MLIRContext * getContext(OpFoldResult val)
static SmallVector< int64_t > getPositionFromIndices(ArrayRef< unsigned > indices)
Converts an array of unsigned indices to a signed integer position array.
static constexpr std::array kExplicitAttributes
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)
static void processMemoryEffects(llvm::Function *func, LLVMFuncOp funcOp)
static constexpr StringRef getGlobalDtorsVarName()
Returns the name of the global_dtors global variables.
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 getGlobalComdatOpName()
Returns the symbol name for the module-level comdat operation.
static constexpr StringRef getGlobalCtorsVarName()
Returns the name of the global_ctors global variables.
static bool isMetadataKillLocation(llvm::DbgVariableIntrinsic *dbgIntr)
Checks if dbgIntr is a kill location that holds metadata instead of an SSA value.
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 bool isScalarType(Type type)
Returns if type is a scalar integer or floating-point type.
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 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:319
Block represents an ordered list of Operations.
Definition: Block.h:31
Operation * getTerminator()
Get the terminator operation of this block.
Definition: Block.cpp:243
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
Definition: Block.cpp:152
UnitAttr getUnitAttr()
Definition: Builders.cpp:114
IntegerAttr getI32IntegerAttr(int32_t value)
Definition: Builders.cpp:216
IntegerAttr getIntegerAttr(Type type, int64_t value)
Definition: Builders.cpp:238
ArrayAttr getI32ArrayAttr(ArrayRef< int32_t > values)
Definition: Builders.cpp:283
FloatAttr getFloatAttr(Type type, double value)
Definition: Builders.cpp:261
IntegerType getI32Type()
Definition: Builders.cpp:83
IntegerAttr getI64IntegerAttr(int64_t value)
Definition: Builders.cpp:128
StringAttr getStringAttr(const Twine &bytes)
Definition: Builders.cpp:269
TypedAttr getZeroAttr(Type type)
Definition: Builders.cpp:331
MLIRContext * getContext() const
Definition: Builders.h:55
ArrayAttr getArrayAttr(ArrayRef< Attribute > value)
Definition: Builders.cpp:273
DictionaryAttr getDictionaryAttr(ArrayRef< NamedAttribute > value)
Definition: Builders.cpp:120
NamedAttribute getNamedAttr(StringRef name, Attribute val)
Definition: Builders.cpp:110
ArrayAttr getStrArrayAttr(ArrayRef< StringRef > values)
Definition: Builders.cpp:313
Attr getAttr(Args &&...args)
Get or construct an instance of the attribute Attr with provided arguments.
Definition: Builders.h:100
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:136
This class provides support for representing a failure result, or a valid value of type T.
Definition: LogicalResult.h:78
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.
static FloatType getBF16(MLIRContext *ctx)
Definition: BuiltinTypes.h:434
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:47
Location translateLoc(llvm::DILocation *loc)
Translates the debug location.
LogicalResult convertComdats()
Converts all comdat selectors of the LLVM module to MLIR comdat operations.
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:117
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 ...
LogicalResult convertIntrinsicArguments(ArrayRef< llvm::Value * > values, 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.
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:56
void addDebugIntrinsic(llvm::CallInst *intrinsic)
Adds a debug intrinsics to the list of intrinsics that should be converted after the function convers...
Block * lookupBlock(llvm::BasicBlock *block) const
Returns the MLIR block mapped to the given LLVM block.
Definition: ModuleImport.h:124
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 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:90
Type convertType(llvm::Type *type)
Converts the type from LLVM to MLIR LLVM dialect.
Definition: ModuleImport.h:172
Operation * lookupOperation(llvm::Instruction *inst)
Returns the MLIR operation mapped to the given LLVM instruction.
Definition: ModuleImport.h:110
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:85
LogicalResult processFunction(llvm::Function *func)
Imports func into the current module.
RoundingModeAttr matchRoundingModeAttr(llvm::Value *value)
Converts value to a rounding mode attribute.
void mapValue(llvm::Value *llvm, Value mlir)
Stores the mapping between an LLVM value and its MLIR counterpart.
Definition: ModuleImport.h:73
ModuleImport(ModuleOp mlirModule, std::unique_ptr< llvm::Module > llvmModule, bool emitExpensiveWarnings, bool importEmptyDICompositeTypes)
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 ...
FPExceptionBehaviorAttr matchFPExceptionBehaviorAttr(llvm::Value *value)
Converts value to a FP exception behavior attribute.
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 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.
DataLayoutSpecInterface getDataLayout() const
Returns the MLIR data layout specification translated from the LLVM data layout.
ArrayRef< StringRef > getUnhandledTokens() const
Returns the data layout tokens that have not been handled during the data layout translation.
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:63
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:60
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:350
This class helps build Operations.
Definition: Builders.h:209
void setInsertionPointToStart(Block *block)
Sets the insertion point to the start of the specified block.
Definition: Builders.h:433
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
Definition: Builders.h:400
void setInsertionPointToEnd(Block *block)
Sets the insertion point to the end of the specified block.
Definition: Builders.h:438
Block * createBlock(Region *parent, Region::iterator insertPt={}, TypeRange argTypes=std::nullopt, ArrayRef< Location > locs=std::nullopt)
Add new block with 'argTypes' arguments and set the insertion point to the end of it.
Definition: Builders.cpp:437
void setInsertionPointAfterValue(Value val)
Sets the insertion point to the node after the specified value.
Definition: Builders.h:423
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
Definition: Builders.cpp:464
void setInsertionPointAfter(Operation *op)
Sets the insertion point to the node after the specified operation, which will cause subsequent inser...
Definition: Builders.h:414
Block * getInsertionBlock() const
Return the block the current insertion point belongs to.
Definition: Builders.h:444
This class provides the API for ops that are known to be terminators.
Definition: OpDefinition.h:764
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:745
Block * getBlock()
Returns the operation block that contains this operation.
Definition: Operation.h:213
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
This class provides an abstraction over the different types of ranges over Values.
Definition: ValueRange.h:381
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:20
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:876
llvm::ElementCount getVectorNumElements(Type type)
Returns the element count of any LLVM-compatible vector type.
Definition: LLVMTypes.cpp:901
Type getVectorElementType(Type type)
Returns the element type of any vector type compatible with the LLVM dialect.
Definition: LLVMTypes.cpp:892
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
Definition: Matchers.h:285
Include the generated interface declarations.
bool matchPattern(Value value, const Pattern &pattern)
Entry point for matching a pattern over a Value.
Definition: Matchers.h:401
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:62
InFlightDiagnostic emitWarning(Location loc)
Utility method to emit a warning message using this location.
OwningOpRef< ModuleOp > translateLLVMIRToModule(std::unique_ptr< llvm::Module > llvmModule, MLIRContext *context, bool emitExpensiveWarnings=true, bool dropDICompositeTypeElements=false)
Translates the LLVM module into an MLIR module living in the given context.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
bool succeeded(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a success value.
Definition: LogicalResult.h:68
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:56
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:310
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
Definition: LogicalResult.h:72
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26