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