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