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