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