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