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