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

source code of mlir/lib/Target/LLVMIR/ModuleImport.cpp