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 AsmDialectAttr::get(
2555 mlirModule.getContext(),
2556 convertAsmDialectFromLLVM(asmI->getDialect())),
2557 operandAttrs)
2558 .getOperation();
2559 }
2560 bool isIncompatibleCall;
2561 FailureOr<LLVMFunctionType> funcTy =
2562 convertFunctionType(callInst, isIncompatibleCall);
2563 if (failed(funcTy))
2564 return failure();
2565
2566 FlatSymbolRefAttr callee = nullptr;
2567 if (isIncompatibleCall) {
2568 // Use an indirect call (in order to represent valid and verifiable LLVM
2569 // IR). Build the indirect call by passing an empty `callee` operand and
2570 // insert into `operands` to include the indirect call target.
2571 FlatSymbolRefAttr calleeSym = convertCalleeName(callInst);
2572 Value indirectCallVal = LLVM::AddressOfOp::create(
2573 builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);
2574 operands->insert(operands->begin(), indirectCallVal);
2575 } else {
2576 // Regular direct call using callee name.
2577 callee = convertCalleeName(callInst);
2578 }
2579 CallOp callOp = CallOp::create(builder, loc, *funcTy, callee, *operands);
2580
2581 if (failed(convertCallAttributes(callInst, callOp)))
2582 return failure();
2583
2584 // Handle parameter and result attributes unless it's an incompatible
2585 // call.
2586 if (!isIncompatibleCall)
2587 convertArgAndResultAttrs(callInst, callOp);
2588 return callOp.getOperation();
2589 }();
2590
2591 if (failed(callOp))
2592 return failure();
2593
2594 if (!callInst->getType()->isVoidTy())
2595 mapValue(inst, (*callOp)->getResult(0));
2596 else
2597 mapNoResultOp(inst, *callOp);
2598 return success();
2599 }
2600 if (inst->getOpcode() == llvm::Instruction::LandingPad) {
2601 auto *lpInst = cast<llvm::LandingPadInst>(inst);
2602
2603 SmallVector<Value> operands;
2604 operands.reserve(lpInst->getNumClauses());
2605 for (auto i : llvm::seq<unsigned>(0, lpInst->getNumClauses())) {
2606 FailureOr<Value> operand = convertValue(lpInst->getClause(i));
2607 if (failed(operand))
2608 return failure();
2609 operands.push_back(*operand);
2610 }
2611
2612 Type type = convertType(lpInst->getType());
2613 auto lpOp =
2614 LandingpadOp::create(builder, loc, type, lpInst->isCleanup(), operands);
2615 mapValue(inst, lpOp);
2616 return success();
2617 }
2618 if (inst->getOpcode() == llvm::Instruction::Invoke) {
2619 auto *invokeInst = cast<llvm::InvokeInst>(inst);
2620
2621 if (invokeInst->isInlineAsm())
2622 return emitError(loc) << "invoke of inline assembly is not supported";
2623
2624 FailureOr<SmallVector<Value>> operands = convertCallOperands(invokeInst);
2625 if (failed(operands))
2626 return failure();
2627
2628 // Check whether the invoke result is an argument to the normal destination
2629 // block.
2630 bool invokeResultUsedInPhi = llvm::any_of(
2631 invokeInst->getNormalDest()->phis(), [&](const llvm::PHINode &phi) {
2632 return phi.getIncomingValueForBlock(invokeInst->getParent()) ==
2633 invokeInst;
2634 });
2635
2636 Block *normalDest = lookupBlock(invokeInst->getNormalDest());
2637 Block *directNormalDest = normalDest;
2638 if (invokeResultUsedInPhi) {
2639 // The invoke result cannot be an argument to the normal destination
2640 // block, as that would imply using the invoke operation result in its
2641 // definition, so we need to create a dummy block to serve as an
2642 // intermediate destination.
2643 OpBuilder::InsertionGuard g(builder);
2644 directNormalDest = builder.createBlock(normalDest);
2645 }
2646
2647 SmallVector<Value> unwindArgs;
2648 if (failed(convertBranchArgs(invokeInst, invokeInst->getUnwindDest(),
2649 unwindArgs)))
2650 return failure();
2651
2652 bool isIncompatibleInvoke;
2653 FailureOr<LLVMFunctionType> funcTy =
2654 convertFunctionType(invokeInst, isIncompatibleInvoke);
2655 if (failed(funcTy))
2656 return failure();
2657
2658 FlatSymbolRefAttr calleeName = nullptr;
2659 if (isIncompatibleInvoke) {
2660 // Use an indirect invoke (in order to represent valid and verifiable LLVM
2661 // IR). Build the indirect invoke by passing an empty `callee` operand and
2662 // insert into `operands` to include the indirect invoke target.
2663 FlatSymbolRefAttr calleeSym = convertCalleeName(invokeInst);
2664 Value indirectInvokeVal = LLVM::AddressOfOp::create(
2665 builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);
2666 operands->insert(operands->begin(), indirectInvokeVal);
2667 } else {
2668 // Regular direct invoke using callee name.
2669 calleeName = convertCalleeName(invokeInst);
2670 }
2671 // Create the invoke operation. Normal destination block arguments will be
2672 // added later on to handle the case in which the operation result is
2673 // included in this list.
2674 auto invokeOp = InvokeOp::create(
2675 builder, loc, *funcTy, calleeName, *operands, directNormalDest,
2676 ValueRange(), lookupBlock(invokeInst->getUnwindDest()), unwindArgs);
2677
2678 if (failed(convertInvokeAttributes(invokeInst, invokeOp)))
2679 return failure();
2680
2681 // Handle parameter and result attributes unless it's an incompatible
2682 // invoke.
2683 if (!isIncompatibleInvoke)
2684 convertArgAndResultAttrs(invokeInst, invokeOp);
2685
2686 if (!invokeInst->getType()->isVoidTy())
2687 mapValue(inst, invokeOp.getResults().front());
2688 else
2689 mapNoResultOp(inst, invokeOp);
2690
2691 SmallVector<Value> normalArgs;
2692 if (failed(convertBranchArgs(invokeInst, invokeInst->getNormalDest(),
2693 normalArgs)))
2694 return failure();
2695
2696 if (invokeResultUsedInPhi) {
2697 // The dummy normal dest block will just host an unconditional branch
2698 // instruction to the normal destination block passing the required block
2699 // arguments (including the invoke operation's result).
2700 OpBuilder::InsertionGuard g(builder);
2701 builder.setInsertionPointToStart(directNormalDest);
2702 LLVM::BrOp::create(builder, loc, normalArgs, normalDest);
2703 } else {
2704 // If the invoke operation's result is not a block argument to the normal
2705 // destination block, just add the block arguments as usual.
2706 assert(llvm::none_of(
2707 normalArgs,
2708 [&](Value val) { return val.getDefiningOp() == invokeOp; }) &&
2709 "An llvm.invoke operation cannot pass its result as a block "
2710 "argument.");
2711 invokeOp.getNormalDestOperandsMutable().append(normalArgs);
2712 }
2713
2714 return success();
2715 }
2716 if (inst->getOpcode() == llvm::Instruction::GetElementPtr) {
2717 auto *gepInst = cast<llvm::GetElementPtrInst>(inst);
2718 Type sourceElementType = convertType(gepInst->getSourceElementType());
2719 FailureOr<Value> basePtr = convertValue(gepInst->getOperand(0));
2720 if (failed(basePtr))
2721 return failure();
2722
2723 // Treat every indices as dynamic since GEPOp::build will refine those
2724 // indices into static attributes later. One small downside of this
2725 // approach is that many unused `llvm.mlir.constant` would be emitted
2726 // at first place.
2727 SmallVector<GEPArg> indices;
2728 for (llvm::Value *operand : llvm::drop_begin(gepInst->operand_values())) {
2729 FailureOr<Value> index = convertValue(operand);
2730 if (failed(index))
2731 return failure();
2732 indices.push_back(*index);
2733 }
2734
2735 Type type = convertType(inst->getType());
2736 auto gepOp = GEPOp::create(
2737 builder, loc, type, sourceElementType, *basePtr, indices,
2738 static_cast<GEPNoWrapFlags>(gepInst->getNoWrapFlags().getRaw()));
2739 mapValue(inst, gepOp);
2740 return success();
2741 }
2742
2743 if (inst->getOpcode() == llvm::Instruction::IndirectBr) {
2744 auto *indBrInst = cast<llvm::IndirectBrInst>(inst);
2745
2746 FailureOr<Value> basePtr = convertValue(indBrInst->getAddress());
2747 if (failed(basePtr))
2748 return failure();
2749
2750 SmallVector<Block *> succBlocks;
2751 SmallVector<SmallVector<Value>> succBlockArgs;
2752 for (auto i : llvm::seq<unsigned>(0, indBrInst->getNumSuccessors())) {
2753 llvm::BasicBlock *succ = indBrInst->getSuccessor(i);
2754 SmallVector<Value> blockArgs;
2755 if (failed(convertBranchArgs(indBrInst, succ, blockArgs)))
2756 return failure();
2757 succBlocks.push_back(lookupBlock(succ));
2758 succBlockArgs.push_back(blockArgs);
2759 }
2760 SmallVector<ValueRange> succBlockArgsRange =
2761 llvm::to_vector_of<ValueRange>(succBlockArgs);
2762 Location loc = translateLoc(inst->getDebugLoc());
2763 auto indBrOp = LLVM::IndirectBrOp::create(builder, loc, *basePtr,
2764 succBlockArgsRange, succBlocks);
2765
2766 mapNoResultOp(inst, indBrOp);
2767 return success();
2768 }
2769
2770 // Convert all instructions that have an mlirBuilder.
2771 if (succeeded(convertInstructionImpl(builder, inst, *this, iface)))
2772 return success();
2773
2774 return emitError(loc) << "unhandled instruction: " << diag(*inst);
2775}
2776
2777LogicalResult ModuleImport::processInstruction(llvm::Instruction *inst) {
2778 // FIXME: Support uses of SubtargetData.
2779 // FIXME: Add support for call / operand attributes.
2780 // FIXME: Add support for the cleanupret, catchret, catchswitch, callbr,
2781 // vaarg, catchpad, cleanuppad instructions.
2782
2783 // Convert LLVM intrinsics calls to MLIR intrinsics.
2784 if (auto *intrinsic = dyn_cast<llvm::IntrinsicInst>(inst))
2785 return convertIntrinsic(intrinsic);
2786
2787 // Process debug records attached to this instruction. Debug variable records
2788 // are stored for later processing after all SSA values are converted, while
2789 // debug label records can be converted immediately.
2790 if (inst->DebugMarker) {
2791 for (llvm::DbgRecord &dbgRecord : inst->DebugMarker->getDbgRecordRange()) {
2792 // Store debug variable records for later processing.
2793 if (auto *dbgVariableRecord =
2794 dyn_cast<llvm::DbgVariableRecord>(&dbgRecord)) {
2795 addDebugRecord(dbgVariableRecord);
2796 continue;
2797 }
2798 Location loc = translateLoc(dbgRecord.getDebugLoc());
2799 auto emitUnsupportedWarning = [&]() -> LogicalResult {
2800 if (!emitExpensiveWarnings)
2801 return success();
2802 std::string options;
2803 llvm::raw_string_ostream optionsStream(options);
2804 dbgRecord.print(optionsStream);
2805 emitWarning(loc) << "unhandled debug record " << optionsStream.str();
2806 return success();
2807 };
2808 // Convert the debug label records in-place.
2809 if (auto *dbgLabelRecord = dyn_cast<llvm::DbgLabelRecord>(&dbgRecord)) {
2810 DILabelAttr labelAttr =
2811 debugImporter->translate(dbgLabelRecord->getLabel());
2812 if (!labelAttr)
2813 return emitUnsupportedWarning();
2814 LLVM::DbgLabelOp::create(builder, loc, labelAttr);
2815 continue;
2816 }
2817 // Warn if an unsupported debug record is encountered.
2818 return emitUnsupportedWarning();
2819 }
2820 }
2821
2822 // Convert all remaining LLVM instructions to MLIR operations.
2823 return convertInstruction(inst);
2824}
2825
2826FlatSymbolRefAttr ModuleImport::getPersonalityAsAttr(llvm::Function *f) {
2827 if (!f->hasPersonalityFn())
2828 return nullptr;
2829
2830 llvm::Constant *pf = f->getPersonalityFn();
2831
2832 // If it directly has a name, we can use it.
2833 if (pf->hasName())
2834 return SymbolRefAttr::get(builder.getContext(), pf->getName());
2835
2836 // If it doesn't have a name, currently, only function pointers that are
2837 // bitcast to i8* are parsed.
2838 if (auto *ce = dyn_cast<llvm::ConstantExpr>(pf)) {
2839 if (ce->getOpcode() == llvm::Instruction::BitCast &&
2840 ce->getType() == llvm::PointerType::getUnqual(f->getContext())) {
2841 if (auto *func = dyn_cast<llvm::Function>(ce->getOperand(0)))
2842 return SymbolRefAttr::get(builder.getContext(), func->getName());
2843 }
2844 }
2845 return FlatSymbolRefAttr();
2846}
2847
2848static void processMemoryEffects(llvm::Function *func, LLVMFuncOp funcOp) {
2849 llvm::MemoryEffects memEffects = func->getMemoryEffects();
2850
2851 auto othermem = convertModRefInfoFromLLVM(
2852 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
2853 auto argMem = convertModRefInfoFromLLVM(
2854 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
2855 auto inaccessibleMem = convertModRefInfoFromLLVM(
2856 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
2857 auto errnoMem = convertModRefInfoFromLLVM(
2858 memEffects.getModRef(llvm::MemoryEffects::Location::ErrnoMem));
2859 auto targetMem0 = convertModRefInfoFromLLVM(
2860 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem0));
2861 auto targetMem1 = convertModRefInfoFromLLVM(
2862 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem1));
2863 auto memAttr =
2864 MemoryEffectsAttr::get(funcOp.getContext(), othermem, argMem,
2865 inaccessibleMem, errnoMem, targetMem0, targetMem1);
2866 // Only set the attr when it does not match the default value.
2867 if (memAttr.isReadWrite())
2868 return;
2869 funcOp.setMemoryEffectsAttr(memAttr);
2870}
2871
2872static void processDenormalFPEnv(llvm::Function *func, LLVMFuncOp funcOp) {
2873 llvm::DenormalFPEnv denormalFpEnv = func->getDenormalFPEnv();
2874 // Only set the attr when it does not match the default value.
2875 if (denormalFpEnv == llvm::DenormalFPEnv::getDefault())
2876 return;
2877
2878 llvm::DenormalMode defaultMode = denormalFpEnv.DefaultMode;
2879 llvm::DenormalMode floatMode = denormalFpEnv.F32Mode;
2880
2881 auto denormalFpEnvAttr = DenormalFPEnvAttr::get(
2882 funcOp.getContext(), convertDenormalModeKindFromLLVM(defaultMode.Output),
2883 convertDenormalModeKindFromLLVM(defaultMode.Input),
2884 convertDenormalModeKindFromLLVM(floatMode.Output),
2885 convertDenormalModeKindFromLLVM(floatMode.Input));
2886 funcOp.setDenormalFpenvAttr(denormalFpEnvAttr);
2887}
2888
2889// List of LLVM IR attributes that map to an explicit attribute on the MLIR
2890// LLVMFuncOp.
2891static constexpr std::array kExplicitLLVMFuncOpAttributes{
2892 StringLiteral("aarch64_in_za"),
2893 StringLiteral("aarch64_inout_za"),
2894 StringLiteral("aarch64_new_za"),
2895 StringLiteral("aarch64_out_za"),
2896 StringLiteral("aarch64_preserves_za"),
2897 StringLiteral("aarch64_pstate_sm_body"),
2898 StringLiteral("aarch64_pstate_sm_compatible"),
2899 StringLiteral("aarch64_pstate_sm_enabled"),
2900 StringLiteral("allocsize"),
2901 StringLiteral("alwaysinline"),
2902 StringLiteral("cold"),
2903 StringLiteral("convergent"),
2904 StringLiteral("fp-contract"),
2905 StringLiteral("frame-pointer"),
2906 StringLiteral("hot"),
2907 StringLiteral("inlinehint"),
2908 StringLiteral("instrument-function-entry"),
2909 StringLiteral("instrument-function-exit"),
2910 StringLiteral("modular-format"),
2911 StringLiteral("memory"),
2912 StringLiteral("minsize"),
2913 StringLiteral("no_caller_saved_registers"),
2914 StringLiteral("no-signed-zeros-fp-math"),
2915 StringLiteral("no-builtins"),
2916 StringLiteral("nocallback"),
2917 StringLiteral("noduplicate"),
2918 StringLiteral("noinline"),
2919 StringLiteral("noreturn"),
2920 StringLiteral("nounwind"),
2921 StringLiteral("optnone"),
2922 StringLiteral("optsize"),
2923 StringLiteral("returns_twice"),
2924 StringLiteral("save-reg-params"),
2925 StringLiteral("target-features"),
2926 StringLiteral("trap-func-name"),
2927 StringLiteral("tune-cpu"),
2928 StringLiteral("uniform-work-group-size"),
2929 StringLiteral("uwtable"),
2930 StringLiteral("vscale_range"),
2931 StringLiteral("willreturn"),
2932 StringLiteral("zero-call-used-regs"),
2933 StringLiteral("denormal_fpenv"),
2934};
2935
2936// List of LLVM IR attributes that are handled by prefix to map onto an MLIR
2937// LLVMFuncOp.
2938static constexpr std::array kExplicitLLVMFuncOpAttributePrefixes{
2939 StringLiteral("no-builtin-"),
2940};
2941
2942template <typename OpTy>
2944 const llvm::AttributeSet &attrs,
2945 OpTy target) {
2946 // 'no-builtins' is the complete collection, and overrides all the rest.
2947 if (attrs.hasAttribute("no-builtins")) {
2948 target.setNobuiltinsAttr(ArrayAttr::get(ctx, {}));
2949 return;
2950 }
2951
2953 for (llvm::Attribute attr : attrs) {
2954 // Attributes that are part of llvm directly (that is, have an AttributeKind
2955 // in the enum) shouldn't be checked.
2956 if (attr.hasKindAsEnum())
2957 continue;
2958
2959 StringRef val = attr.getKindAsString();
2960
2961 if (val.starts_with("no-builtin-"))
2962 nbAttrs.insert(
2963 StringAttr::get(ctx, val.drop_front(sizeof("no-builtin-") - 1)));
2964 }
2965
2966 if (!nbAttrs.empty())
2967 target.setNobuiltinsAttr(ArrayAttr::get(ctx, nbAttrs.getArrayRef()));
2968}
2969
2970template <typename OpTy>
2972 const llvm::AttributeSet &attrs, OpTy target) {
2973 llvm::Attribute attr = attrs.getAttribute(llvm::Attribute::AllocSize);
2974 if (!attr.isValid())
2975 return;
2976
2977 auto [elemSize, numElems] = attr.getAllocSizeArgs();
2978 if (numElems) {
2979 target.setAllocsizeAttr(
2980 DenseI32ArrayAttr::get(ctx, {static_cast<int32_t>(elemSize),
2981 static_cast<int32_t>(*numElems)}));
2982 } else {
2983 target.setAllocsizeAttr(
2984 DenseI32ArrayAttr::get(ctx, {static_cast<int32_t>(elemSize)}));
2985 }
2986}
2987
2988/// Converts LLVM attributes from `func` into MLIR attributes and adds them
2989/// to `funcOp` as passthrough attributes, skipping those listed in
2990/// `kExplicitLLVMFuncAttributes`.
2991static void processPassthroughAttrs(llvm::Function *func, LLVMFuncOp funcOp) {
2992 llvm::AttributeSet funcAttrs = func->getAttributes().getAttributes(
2993 llvm::AttributeList::AttrIndex::FunctionIndex);
2994 ArrayAttr passthroughAttr = convertLLVMAttributesToMLIR(
2995 funcOp.getLoc(), funcOp.getContext(), funcAttrs,
2997 if (!passthroughAttr.empty())
2998 funcOp.setPassthroughAttr(passthroughAttr);
2999}
3000
3002 LLVMFuncOp funcOp) {
3003 processMemoryEffects(func, funcOp);
3004 processDenormalFPEnv(func, funcOp);
3006
3007 if (func->hasFnAttribute(llvm::Attribute::NoInline))
3008 funcOp.setNoInline(true);
3009 if (func->hasFnAttribute(llvm::Attribute::AlwaysInline))
3010 funcOp.setAlwaysInline(true);
3011 if (func->hasFnAttribute(llvm::Attribute::InlineHint))
3012 funcOp.setInlineHint(true);
3013 if (func->hasFnAttribute(llvm::Attribute::OptimizeNone))
3014 funcOp.setOptimizeNone(true);
3015 if (func->hasFnAttribute(llvm::Attribute::Convergent))
3016 funcOp.setConvergent(true);
3017 if (func->hasFnAttribute(llvm::Attribute::NoUnwind))
3018 funcOp.setNoUnwind(true);
3019 if (func->hasFnAttribute(llvm::Attribute::WillReturn))
3020 funcOp.setWillReturn(true);
3021 if (func->hasFnAttribute(llvm::Attribute::NoReturn))
3022 funcOp.setNoreturn(true);
3023 if (func->hasFnAttribute(llvm::Attribute::OptimizeForSize))
3024 funcOp.setOptsize(true);
3025 if (func->hasFnAttribute("save-reg-params"))
3026 funcOp.setSaveRegParams(true);
3027 if (func->hasFnAttribute("uniform-work-group-size"))
3028 funcOp.setUniformWorkGroupSize(true);
3029 if (func->hasFnAttribute(llvm::Attribute::MinSize))
3030 funcOp.setMinsize(true);
3031 if (func->hasFnAttribute(llvm::Attribute::ReturnsTwice))
3032 funcOp.setReturnsTwice(true);
3033 if (func->hasFnAttribute(llvm::Attribute::Cold))
3034 funcOp.setCold(true);
3035 if (func->hasFnAttribute(llvm::Attribute::Hot))
3036 funcOp.setHot(true);
3037 if (func->hasFnAttribute(llvm::Attribute::NoDuplicate))
3038 funcOp.setNoduplicate(true);
3039 if (func->hasFnAttribute("no_caller_saved_registers"))
3040 funcOp.setNoCallerSavedRegisters(true);
3041 if (func->hasFnAttribute(llvm::Attribute::NoCallback))
3042 funcOp.setNocallback(true);
3043 if (llvm::Attribute attr = func->getFnAttribute("modular-format");
3044 attr.isStringAttribute())
3045 funcOp.setModularFormat(StringAttr::get(context, attr.getValueAsString()));
3046 if (llvm::Attribute attr = func->getFnAttribute("zero-call-used-regs");
3047 attr.isStringAttribute())
3048 funcOp.setZeroCallUsedRegsAttr(
3049 StringAttr::get(context, attr.getValueAsString()));
3050
3051 if (func->hasFnAttribute("aarch64_pstate_sm_enabled"))
3052 funcOp.setArmStreaming(true);
3053 else if (func->hasFnAttribute("aarch64_pstate_sm_body"))
3054 funcOp.setArmLocallyStreaming(true);
3055 else if (func->hasFnAttribute("aarch64_pstate_sm_compatible"))
3056 funcOp.setArmStreamingCompatible(true);
3057
3058 if (func->hasFnAttribute("aarch64_new_za"))
3059 funcOp.setArmNewZa(true);
3060 else if (func->hasFnAttribute("aarch64_in_za"))
3061 funcOp.setArmInZa(true);
3062 else if (func->hasFnAttribute("aarch64_out_za"))
3063 funcOp.setArmOutZa(true);
3064 else if (func->hasFnAttribute("aarch64_inout_za"))
3065 funcOp.setArmInoutZa(true);
3066 else if (func->hasFnAttribute("aarch64_preserves_za"))
3067 funcOp.setArmPreservesZa(true);
3068
3069 convertNoBuiltinAttrs(context, func->getAttributes().getFnAttrs(), funcOp);
3070 convertAllocsizeAttr(context, func->getAttributes().getFnAttrs(), funcOp);
3071
3072 llvm::Attribute attr = func->getFnAttribute(llvm::Attribute::VScaleRange);
3073 if (attr.isValid()) {
3074 MLIRContext *context = funcOp.getContext();
3075 auto intTy = IntegerType::get(context, 32);
3076 funcOp.setVscaleRangeAttr(LLVM::VScaleRangeAttr::get(
3077 context, IntegerAttr::get(intTy, attr.getVScaleRangeMin()),
3078 IntegerAttr::get(intTy, attr.getVScaleRangeMax().value_or(0))));
3079 }
3080
3081 // Process frame-pointer attribute.
3082 if (func->hasFnAttribute("frame-pointer")) {
3083 StringRef stringRefFramePointerKind =
3084 func->getFnAttribute("frame-pointer").getValueAsString();
3085 funcOp.setFramePointerAttr(LLVM::FramePointerKindAttr::get(
3086 funcOp.getContext(), LLVM::framePointerKind::symbolizeFramePointerKind(
3087 stringRefFramePointerKind)
3088 .value()));
3089 }
3090
3091 if (func->hasFnAttribute("use-sample-profile"))
3092 funcOp.setUseSampleProfile(true);
3093
3094 if (llvm::Attribute attr = func->getFnAttribute("target-cpu");
3095 attr.isStringAttribute())
3096 funcOp.setTargetCpuAttr(StringAttr::get(context, attr.getValueAsString()));
3097
3098 if (llvm::Attribute attr = func->getFnAttribute("tune-cpu");
3099 attr.isStringAttribute())
3100 funcOp.setTuneCpuAttr(StringAttr::get(context, attr.getValueAsString()));
3101
3102 if (llvm::Attribute attr = func->getFnAttribute("target-features");
3103 attr.isStringAttribute())
3104 funcOp.setTargetFeaturesAttr(
3105 LLVM::TargetFeaturesAttr::get(context, attr.getValueAsString()));
3106
3107 if (llvm::Attribute attr = func->getFnAttribute("reciprocal-estimates");
3108 attr.isStringAttribute())
3109 funcOp.setReciprocalEstimatesAttr(
3110 StringAttr::get(context, attr.getValueAsString()));
3111
3112 if (llvm::Attribute attr = func->getFnAttribute("prefer-vector-width");
3113 attr.isStringAttribute())
3114 funcOp.setPreferVectorWidth(attr.getValueAsString());
3115
3116 if (llvm::Attribute attr = func->getFnAttribute("instrument-function-entry");
3117 attr.isStringAttribute())
3118 funcOp.setInstrumentFunctionEntry(
3119 StringAttr::get(context, attr.getValueAsString()));
3120
3121 if (llvm::Attribute attr = func->getFnAttribute("instrument-function-exit");
3122 attr.isStringAttribute())
3123 funcOp.setInstrumentFunctionExit(
3124 StringAttr::get(context, attr.getValueAsString()));
3125
3126 if (llvm::Attribute attr = func->getFnAttribute("no-signed-zeros-fp-math");
3127 attr.isStringAttribute())
3128 funcOp.setNoSignedZerosFpMath(attr.getValueAsBool());
3129
3130 if (llvm::Attribute attr = func->getFnAttribute("fp-contract");
3131 attr.isStringAttribute())
3132 funcOp.setFpContractAttr(StringAttr::get(context, attr.getValueAsString()));
3133
3134 if (func->hasUWTable()) {
3135 ::llvm::UWTableKind uwtableKind = func->getUWTableKind();
3136 funcOp.setUwtableKindAttr(LLVM::UWTableKindAttr::get(
3137 funcOp.getContext(), convertUWTableKindFromLLVM(uwtableKind)));
3138 }
3139}
3140
3141DictionaryAttr
3142ModuleImport::convertArgOrResultAttrSet(llvm::AttributeSet llvmAttrSet) {
3143 SmallVector<NamedAttribute> paramAttrs;
3144 for (auto [llvmKind, mlirName] : getAttrKindToNameMapping()) {
3145 auto llvmAttr = llvmAttrSet.getAttribute(llvmKind);
3146 // Skip attributes that are not attached.
3147 if (!llvmAttr.isValid())
3148 continue;
3149
3150 // TODO: Import captures(none) as a nocapture unit attribute until the
3151 // LLVM dialect switches to the captures representation.
3152 if (llvmAttr.hasKindAsEnum() &&
3153 llvmAttr.getKindAsEnum() == llvm::Attribute::Captures) {
3154 if (llvm::capturesNothing(llvmAttr.getCaptureInfo()))
3155 paramAttrs.push_back(
3156 builder.getNamedAttr(mlirName, builder.getUnitAttr()));
3157 continue;
3158 }
3159
3160 Attribute mlirAttr;
3161 if (llvmAttr.isTypeAttribute())
3162 mlirAttr = TypeAttr::get(convertType(llvmAttr.getValueAsType()));
3163 else if (llvmAttr.isIntAttribute())
3164 mlirAttr = builder.getI64IntegerAttr(llvmAttr.getValueAsInt());
3165 else if (llvmAttr.isEnumAttribute())
3166 mlirAttr = builder.getUnitAttr();
3167 else if (llvmAttr.isConstantRangeAttribute()) {
3168 const llvm::ConstantRange &value = llvmAttr.getValueAsConstantRange();
3169 mlirAttr = builder.getAttr<LLVM::ConstantRangeAttr>(value.getLower(),
3170 value.getUpper());
3171 } else {
3172 llvm_unreachable("unexpected parameter attribute kind");
3173 }
3174 paramAttrs.push_back(builder.getNamedAttr(mlirName, mlirAttr));
3175 }
3176
3177 return builder.getDictionaryAttr(paramAttrs);
3178}
3179
3180void ModuleImport::convertArgAndResultAttrs(llvm::Function *func,
3181 LLVMFuncOp funcOp) {
3182 auto llvmAttrs = func->getAttributes();
3183 for (size_t i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
3184 llvm::AttributeSet llvmArgAttrs = llvmAttrs.getParamAttrs(i);
3185 funcOp.setArgAttrs(i, convertArgOrResultAttrSet(llvmArgAttrs));
3186 }
3187 // Convert the result attributes and attach them wrapped in an ArrayAttribute
3188 // to the funcOp.
3189 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
3190 if (!llvmResAttr.hasAttributes())
3191 return;
3192 funcOp.setResAttrsAttr(
3193 builder.getArrayAttr({convertArgOrResultAttrSet(llvmResAttr)}));
3194}
3195
3197 llvm::CallBase *call, ArgAndResultAttrsOpInterface attrsOp,
3198 ArrayRef<unsigned> immArgPositions) {
3199 // Compute the set of immediate argument positions.
3200 llvm::SmallDenseSet<unsigned> immArgPositionsSet(immArgPositions.begin(),
3201 immArgPositions.end());
3202 // Convert the argument attributes and filter out immediate arguments.
3203 llvm::AttributeList llvmAttrs = call->getAttributes();
3204 SmallVector<llvm::AttributeSet> llvmArgAttrsSet;
3205 bool anyArgAttrs = false;
3206 for (size_t i = 0, e = call->arg_size(); i < e; ++i) {
3207 // Skip immediate arguments.
3208 if (immArgPositionsSet.contains(i))
3209 continue;
3210 llvmArgAttrsSet.emplace_back(llvmAttrs.getParamAttrs(i));
3211 if (llvmArgAttrsSet.back().hasAttributes())
3212 anyArgAttrs = true;
3213 }
3214 auto getArrayAttr = [&](ArrayRef<DictionaryAttr> dictAttrs) {
3216 for (auto &dict : dictAttrs)
3217 attrs.push_back(dict ? dict : builder.getDictionaryAttr({}));
3218 return builder.getArrayAttr(attrs);
3219 };
3220 if (anyArgAttrs) {
3222 for (auto &llvmArgAttrs : llvmArgAttrsSet)
3223 argAttrs.emplace_back(convertArgOrResultAttrSet(llvmArgAttrs));
3224 attrsOp.setArgAttrsAttr(getArrayAttr(argAttrs));
3225 }
3226
3227 // Convert the result attributes.
3228 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
3229 if (!llvmResAttr.hasAttributes())
3230 return;
3231 DictionaryAttr resAttrs = convertArgOrResultAttrSet(llvmResAttr);
3232 attrsOp.setResAttrsAttr(getArrayAttr({resAttrs}));
3233}
3234
3235template <typename Op>
3236static LogicalResult convertCallBaseAttributes(llvm::CallBase *inst, Op op) {
3237 op.setCConv(convertCConvFromLLVM(inst->getCallingConv()));
3238 return success();
3239}
3240
3241LogicalResult ModuleImport::convertInvokeAttributes(llvm::InvokeInst *inst,
3242 InvokeOp op) {
3243 llvm::AttributeList invokeAttrs = inst->getAttributes();
3244 op.setUniformWorkGroupSize(
3245 invokeAttrs.getFnAttr("uniform-work-group-size").isValid());
3246 return convertCallBaseAttributes(inst, op);
3247}
3248
3249LogicalResult ModuleImport::convertCallAttributes(llvm::CallInst *inst,
3250 CallOp op) {
3251 setFastmathFlagsAttr(inst, op.getOperation());
3252 // Query the attributes directly instead of using `inst->getFnAttr(Kind)`, the
3253 // latter does additional lookup to the parent and inherits, changing the
3254 // semantics too early.
3255 llvm::AttributeList callAttrs = inst->getAttributes();
3256
3257 op.setTailCallKind(convertTailCallKindFromLLVM(inst->getTailCallKind()));
3258 op.setConvergent(callAttrs.getFnAttr(llvm::Attribute::Convergent).isValid());
3259 op.setNoUnwind(callAttrs.getFnAttr(llvm::Attribute::NoUnwind).isValid());
3260 op.setWillReturn(callAttrs.getFnAttr(llvm::Attribute::WillReturn).isValid());
3261 op.setNoreturn(callAttrs.getFnAttr(llvm::Attribute::NoReturn).isValid());
3262 op.setOptsize(
3263 callAttrs.getFnAttr(llvm::Attribute::OptimizeForSize).isValid());
3264 op.setSaveRegParams(callAttrs.getFnAttr("save-reg-params").isValid());
3265 op.setUniformWorkGroupSize(
3266 callAttrs.getFnAttr("uniform-work-group-size").isValid());
3267 op.setBuiltin(callAttrs.getFnAttr(llvm::Attribute::Builtin).isValid());
3268 op.setNobuiltin(callAttrs.getFnAttr(llvm::Attribute::NoBuiltin).isValid());
3269 op.setMinsize(callAttrs.getFnAttr(llvm::Attribute::MinSize).isValid());
3270
3271 op.setReturnsTwice(
3272 callAttrs.getFnAttr(llvm::Attribute::ReturnsTwice).isValid());
3273 op.setHot(callAttrs.getFnAttr(llvm::Attribute::Hot).isValid());
3274 op.setCold(callAttrs.getFnAttr(llvm::Attribute::Cold).isValid());
3275 op.setNoduplicate(
3276 callAttrs.getFnAttr(llvm::Attribute::NoDuplicate).isValid());
3277 op.setNoCallerSavedRegisters(
3278 callAttrs.getFnAttr("no_caller_saved_registers").isValid());
3279 op.setNocallback(callAttrs.getFnAttr(llvm::Attribute::NoCallback).isValid());
3280
3281 if (llvm::Attribute attr = callAttrs.getFnAttr("modular-format");
3282 attr.isStringAttribute())
3283 op.setModularFormat(StringAttr::get(context, attr.getValueAsString()));
3284 if (llvm::Attribute attr = callAttrs.getFnAttr("zero-call-used-regs");
3285 attr.isStringAttribute())
3286 op.setZeroCallUsedRegsAttr(
3287 StringAttr::get(context, attr.getValueAsString()));
3288 if (llvm::Attribute attr = callAttrs.getFnAttr("trap-func-name");
3289 attr.isStringAttribute())
3290 op.setTrapFuncNameAttr(StringAttr::get(context, attr.getValueAsString()));
3291 op.setNoInline(callAttrs.getFnAttr(llvm::Attribute::NoInline).isValid());
3292 op.setAlwaysInline(
3293 callAttrs.getFnAttr(llvm::Attribute::AlwaysInline).isValid());
3294 op.setInlineHint(callAttrs.getFnAttr(llvm::Attribute::InlineHint).isValid());
3295
3296 llvm::MemoryEffects memEffects = inst->getMemoryEffects();
3297 ModRefInfo othermem = convertModRefInfoFromLLVM(
3298 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
3299 ModRefInfo argMem = convertModRefInfoFromLLVM(
3300 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
3301 ModRefInfo inaccessibleMem = convertModRefInfoFromLLVM(
3302 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
3303 ModRefInfo errnoMem = convertModRefInfoFromLLVM(
3304 memEffects.getModRef(llvm::MemoryEffects::Location::ErrnoMem));
3305 ModRefInfo targetMem0 = convertModRefInfoFromLLVM(
3306 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem0));
3307 ModRefInfo targetMem1 = convertModRefInfoFromLLVM(
3308 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem1));
3309 auto memAttr =
3310 MemoryEffectsAttr::get(op.getContext(), othermem, argMem, inaccessibleMem,
3311 errnoMem, targetMem0, targetMem1);
3312 // Only set the attribute when it does not match the default value.
3313 if (!memAttr.isReadWrite())
3314 op.setMemoryEffectsAttr(memAttr);
3315
3316 convertNoBuiltinAttrs(op.getContext(), callAttrs.getFnAttrs(), op);
3317 convertAllocsizeAttr(op.getContext(), callAttrs.getFnAttrs(), op);
3318
3319 return convertCallBaseAttributes(inst, op);
3320}
3321
3322LogicalResult ModuleImport::processFunction(llvm::Function *func) {
3323 clearRegionState();
3324
3325 auto functionType =
3326 dyn_cast<LLVMFunctionType>(convertType(func->getFunctionType()));
3327 if (func->isIntrinsic() &&
3328 iface.isConvertibleIntrinsic(func->getIntrinsicID()))
3329 return success();
3330
3331 bool dsoLocal = func->isDSOLocal();
3332 CConv cconv = convertCConvFromLLVM(func->getCallingConv());
3333
3334 // Insert the function at the end of the module.
3335 OpBuilder::InsertionGuard guard(builder);
3336 builder.setInsertionPointToEnd(mlirModule.getBody());
3337
3338 Location loc = debugImporter->translateFuncLocation(func);
3339 LLVMFuncOp funcOp = LLVMFuncOp::create(
3340 builder, loc, func->getName(), functionType,
3341 convertLinkageFromLLVM(func->getLinkage()), dsoLocal, cconv);
3342
3344
3345 if (FlatSymbolRefAttr personality = getPersonalityAsAttr(func))
3346 funcOp.setPersonalityAttr(personality);
3347 else if (func->hasPersonalityFn())
3348 emitWarning(funcOp.getLoc(), "could not deduce personality, skipping it");
3349
3350 if (func->hasGC())
3351 funcOp.setGarbageCollector(StringRef(func->getGC()));
3352
3353 if (func->hasAtLeastLocalUnnamedAddr())
3354 funcOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(func->getUnnamedAddr()));
3355
3356 if (func->hasSection())
3357 funcOp.setSection(StringRef(func->getSection()));
3358
3359 funcOp.setVisibility_(convertVisibilityFromLLVM(func->getVisibility()));
3360
3361 if (func->hasComdat())
3362 funcOp.setComdatAttr(comdatMapping.lookup(func->getComdat()));
3363
3364 if (llvm::MaybeAlign maybeAlign = func->getAlign())
3365 funcOp.setAlignment(maybeAlign->value());
3366
3367 // Handle Function attributes.
3369
3370 // Convert non-debug metadata by using the dialect interface. Metadata without
3371 // a kind-specific conversion is preserved in the generic function metadata
3372 // carrier.
3374 func->getAllMetadata(allMetadata);
3375 SmallVector<StringRef> metadataNames;
3376 llvmModule->getMDKindNames(metadataNames);
3377 SmallVector<Attribute> functionMetadata;
3378 for (auto &[kind, node] : allMetadata) {
3379 if (kind == llvm::LLVMContext::MD_dbg)
3380 continue;
3381
3382 llvm::MDNode *metadataNode = node;
3383 auto emitUnhandledFunctionMetadataWarning = [&]() {
3384 emitWarning(funcOp.getLoc())
3385 << "unhandled function metadata: "
3386 << diagMD(metadataNode, llvmModule.get()) << " on " << diag(*func);
3387 };
3388
3389 if (iface.isConvertibleMetadata(kind)) {
3390 if (succeeded(iface.setMetadataAttrs(builder, kind, metadataNode, funcOp,
3391 *this)))
3392 continue;
3393 emitUnhandledFunctionMetadataWarning();
3394 continue;
3395 }
3396
3397 Attribute nodeAttr = convertMetadataToAttr(metadataNode);
3398 auto mdNodeAttr = dyn_cast_if_present<LLVM::MDNodeAttr>(nodeAttr);
3399 if (!mdNodeAttr || kind >= metadataNames.size()) {
3400 emitUnhandledFunctionMetadataWarning();
3401 continue;
3402 }
3403
3404 functionMetadata.push_back(LLVM::FunctionMetadataAttr::get(
3405 context, builder.getStringAttr(metadataNames[kind]), mdNodeAttr));
3406 }
3407 if (!functionMetadata.empty())
3408 funcOp.setFunctionMetadataAttr(builder.getArrayAttr(functionMetadata));
3409
3410 if (func->isDeclaration())
3411 return success();
3412
3413 // Collect the set of basic blocks reachable from the function's entry block.
3414 // This step is crucial as LLVM IR can contain unreachable blocks that
3415 // self-dominate. As a result, an operation might utilize a variable it
3416 // defines, which the import does not support. Given that MLIR lacks block
3417 // label support, we can safely remove unreachable blocks, as there are no
3418 // indirect branch instructions that could potentially target these blocks.
3419 llvm::df_iterator_default_set<llvm::BasicBlock *> reachable;
3420 for (llvm::BasicBlock *basicBlock : llvm::depth_first_ext(func, reachable))
3421 (void)basicBlock;
3422
3423 // Eagerly create all reachable blocks.
3424 SmallVector<llvm::BasicBlock *> reachableBasicBlocks;
3425 for (llvm::BasicBlock &basicBlock : *func) {
3426 // Skip unreachable blocks.
3427 if (!reachable.contains(&basicBlock)) {
3428 if (basicBlock.hasAddressTaken())
3429 return emitError(funcOp.getLoc())
3430 << "unreachable block '" << basicBlock.getName()
3431 << "' with address taken";
3432 continue;
3433 }
3434 Region &body = funcOp.getBody();
3435 Block *block = builder.createBlock(&body, body.end());
3436 mapBlock(&basicBlock, block);
3437 reachableBasicBlocks.push_back(&basicBlock);
3438 }
3439
3440 // Add function arguments to the entry block.
3441 for (const auto &it : llvm::enumerate(func->args())) {
3442 BlockArgument blockArg = funcOp.getFunctionBody().addArgument(
3443 functionType.getParamType(it.index()), funcOp.getLoc());
3444 mapValue(&it.value(), blockArg);
3445 }
3446
3447 // Process the blocks in topological order. The ordered traversal ensures
3448 // operands defined in a dominating block have a valid mapping to an MLIR
3449 // value once a block is translated.
3451 getTopologicallySortedBlocks(reachableBasicBlocks);
3452 setConstantInsertionPointToStart(lookupBlock(blocks.front()));
3453 for (llvm::BasicBlock *basicBlock : blocks)
3454 if (failed(processBasicBlock(basicBlock, lookupBlock(basicBlock))))
3455 return failure();
3456
3457 // Process the debug intrinsics that require a delayed conversion after
3458 // everything else was converted.
3459 if (failed(processDebugIntrinsics()))
3460 return failure();
3461
3462 // Process the debug records that require a delayed conversion after
3463 // everything else was converted.
3464 if (failed(processDebugRecords()))
3465 return failure();
3466
3467 return success();
3468}
3469
3470/// Checks if `dbgIntr` is a kill location that holds metadata instead of an SSA
3471/// value.
3472static bool isMetadataKillLocation(llvm::DbgVariableIntrinsic *dbgIntr) {
3473 if (!dbgIntr->isKillLocation())
3474 return false;
3475 llvm::Value *value = dbgIntr->getArgOperand(0);
3476 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
3477 if (!nodeAsVal)
3478 return false;
3479 return !isa<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
3480}
3481
3482/// Ensure that the debug intrinsic is inserted right after the operand
3483/// definition. Otherwise, the operand might not necessarily dominate the
3484/// intrinsic. If the defining operation is a terminator, insert the intrinsic
3485/// into a dominated block.
3487 mlir::OpBuilder &builder, DominanceInfo &domInfo, Value argOperand) {
3488 if (Operation *op = argOperand.getDefiningOp();
3489 op && op->hasTrait<OpTrait::IsTerminator>()) {
3490 // Find a dominated block that can hold the debug intrinsic.
3491 auto dominatedBlocks = domInfo.getNode(op->getBlock())->children();
3492 // If no block is dominated by the terminator, this intrinisc cannot be
3493 // converted.
3494 if (dominatedBlocks.empty())
3495 return failure();
3496 // Set insertion point before the terminator, to avoid inserting something
3497 // before landingpads.
3498 Block *dominatedBlock = (*dominatedBlocks.begin())->getBlock();
3499 builder.setInsertionPoint(dominatedBlock->getTerminator());
3500 } else {
3501 Value insertPt = argOperand;
3502 if (auto blockArg = dyn_cast<BlockArgument>(argOperand)) {
3503 // The value might be coming from a phi node and is now a block argument,
3504 // which means the insertion point is set to the start of the block. If
3505 // this block is a target destination of an invoke, the insertion point
3506 // must happen after the landing pad operation.
3507 Block *insertionBlock = argOperand.getParentBlock();
3508 if (!insertionBlock->empty() &&
3509 isa<LandingpadOp>(insertionBlock->front()))
3510 insertPt = cast<LandingpadOp>(insertionBlock->front()).getRes();
3511 }
3512
3513 builder.setInsertionPointAfterValue(insertPt);
3514 }
3515 return success();
3516}
3517
3518std::tuple<DILocalVariableAttr, DIExpressionAttr, Value>
3519ModuleImport::processDebugOpArgumentsAndInsertionPt(
3520 Location loc,
3521 llvm::function_ref<FailureOr<Value>()> convertArgOperandToValue,
3522 llvm::Value *address,
3523 llvm::PointerUnion<llvm::Value *, llvm::DILocalVariable *> variable,
3524 llvm::DIExpression *expression, DominanceInfo &domInfo) {
3525 // Drop debug intrinsics if the associated debug information cannot be
3526 // translated due to an unsupported construct.
3527 DILocalVariableAttr localVarAttr = matchLocalVariableAttr(variable);
3528 if (!localVarAttr)
3529 return {};
3530 FailureOr<Value> argOperand = convertArgOperandToValue();
3531 if (failed(argOperand)) {
3532 emitError(loc) << "failed to convert a debug operand: " << diag(*address);
3533 return {};
3534 }
3535
3536 if (setDebugIntrinsicBuilderInsertionPoint(builder, domInfo, *argOperand)
3537 .failed())
3538 return {};
3539
3540 return {localVarAttr, debugImporter->translateExpression(expression),
3541 *argOperand};
3542}
3543
3544LogicalResult
3545ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr,
3546 DominanceInfo &domInfo) {
3547 Location loc = translateLoc(dbgIntr->getDebugLoc());
3548 auto emitUnsupportedWarning = [&]() {
3549 if (emitExpensiveWarnings)
3550 emitWarning(loc) << "dropped intrinsic: " << diag(*dbgIntr);
3551 return success();
3552 };
3553
3554 OpBuilder::InsertionGuard guard(builder);
3555 auto convertArgOperandToValue = [&]() {
3556 return convertMetadataValue(dbgIntr->getArgOperand(0));
3557 };
3558
3559 // Drop debug intrinsics with an argument list.
3560 // TODO: Support this case.
3561 if (dbgIntr->hasArgList())
3562 return emitUnsupportedWarning();
3563
3564 // Drop debug intrinsics with kill locations that have metadata nodes as
3565 // location operand, which cannot be converted to poison as the type cannot be
3566 // reconstructed.
3567 // TODO: Support this case.
3568 if (isMetadataKillLocation(dbgIntr))
3569 return emitUnsupportedWarning();
3570
3571 auto [localVariableAttr, locationExprAttr, locVal] =
3572 processDebugOpArgumentsAndInsertionPt(
3573 loc, convertArgOperandToValue, dbgIntr->getArgOperand(0),
3574 dbgIntr->getArgOperand(1), dbgIntr->getExpression(), domInfo);
3575
3576 if (!localVariableAttr)
3577 return emitUnsupportedWarning();
3578
3579 if (!locVal) // Expected if localVariableAttr is present.
3580 return failure();
3581
3582 Operation *op = nullptr;
3583 if (isa<llvm::DbgDeclareInst>(dbgIntr))
3584 op = LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,
3585 locationExprAttr);
3586 else if (isa<llvm::DbgValueInst>(dbgIntr))
3587 op = LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,
3588 locationExprAttr);
3589 else
3590 return emitUnsupportedWarning();
3591
3592 mapNoResultOp(dbgIntr, op);
3593 setNonDebugMetadataAttrs(dbgIntr, op);
3594 return success();
3595}
3596
3597LogicalResult
3598ModuleImport::processDebugRecord(llvm::DbgVariableRecord &dbgRecord,
3599 DominanceInfo &domInfo) {
3600 OpBuilder::InsertionGuard guard(builder);
3601 Location loc = translateLoc(dbgRecord.getDebugLoc());
3602 auto emitUnsupportedWarning = [&]() -> LogicalResult {
3603 if (!emitExpensiveWarnings)
3604 return success();
3605 std::string options;
3606 llvm::raw_string_ostream optionsStream(options);
3607 dbgRecord.print(optionsStream);
3608 emitWarning(loc) << "unhandled debug variable record "
3609 << optionsStream.str();
3610 return success();
3611 };
3612
3613 // Drop debug records with an argument list.
3614 // TODO: Support this case.
3615 if (dbgRecord.hasArgList())
3616 return emitUnsupportedWarning();
3617
3618 // Drop all other debug records with a address operand that cannot be
3619 // converted to an SSA value such as an empty metadata node.
3620 // TODO: Support this case.
3621 if (!dbgRecord.getAddress())
3622 return emitUnsupportedWarning();
3623
3624 auto convertArgOperandToValue = [&]() -> FailureOr<Value> {
3625 llvm::Value *value = dbgRecord.getAddress();
3626
3627 // Return the mapped value if it has been converted before.
3628 auto it = valueMapping.find(value);
3629 if (it != valueMapping.end())
3630 return it->getSecond();
3631
3632 // Convert constants such as immediate values that have no mapping yet.
3633 if (auto *constant = dyn_cast<llvm::Constant>(value))
3634 return convertConstantExpr(constant);
3635 return failure();
3636 };
3637
3638 auto [localVariableAttr, locationExprAttr, locVal] =
3639 processDebugOpArgumentsAndInsertionPt(
3640 loc, convertArgOperandToValue, dbgRecord.getAddress(),
3641 dbgRecord.getVariable(), dbgRecord.getExpression(), domInfo);
3642
3643 if (!localVariableAttr)
3644 return emitUnsupportedWarning();
3645
3646 if (!locVal) // Expected if localVariableAttr is present.
3647 return failure();
3648
3649 if (dbgRecord.isDbgDeclare())
3650 LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,
3651 locationExprAttr);
3652 else if (dbgRecord.isDbgValue())
3653 LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,
3654 locationExprAttr);
3655 else // isDbgAssign
3656 return emitUnsupportedWarning();
3657
3658 return success();
3659}
3660
3661LogicalResult ModuleImport::processDebugIntrinsics() {
3662 DominanceInfo domInfo;
3663 for (llvm::Instruction *inst : debugIntrinsics) {
3664 auto *intrCall = cast<llvm::DbgVariableIntrinsic>(inst);
3665 if (failed(processDebugIntrinsic(intrCall, domInfo)))
3666 return failure();
3667 }
3668 return success();
3669}
3670
3671LogicalResult ModuleImport::processDebugRecords() {
3672 DominanceInfo domInfo;
3673 for (llvm::DbgVariableRecord *dbgRecord : dbgRecords)
3674 if (failed(processDebugRecord(*dbgRecord, domInfo)))
3675 return failure();
3676 dbgRecords.clear();
3677 return success();
3678}
3679
3680LogicalResult ModuleImport::processBasicBlock(llvm::BasicBlock *bb,
3681 Block *block) {
3682 builder.setInsertionPointToStart(block);
3683 for (llvm::Instruction &inst : *bb) {
3684 if (failed(processInstruction(&inst)))
3685 return failure();
3686
3687 // Skip additional processing when the instructions is a debug intrinsics
3688 // that was not yet converted.
3689 if (debugIntrinsics.contains(&inst))
3690 continue;
3691
3692 // Set the non-debug metadata attributes on the imported operation and emit
3693 // a warning if an instruction other than a phi instruction is dropped
3694 // during the import.
3695 if (Operation *op = lookupOperation(&inst)) {
3696 setNonDebugMetadataAttrs(&inst, op);
3697 } else if (inst.getOpcode() != llvm::Instruction::PHI) {
3698 if (emitExpensiveWarnings) {
3699 Location loc = debugImporter->translateLoc(inst.getDebugLoc());
3700 emitWarning(loc) << "dropped instruction: " << diag(inst);
3701 }
3702 }
3703 }
3704
3705 if (bb->hasAddressTaken()) {
3706 OpBuilder::InsertionGuard guard(builder);
3707 builder.setInsertionPointToStart(block);
3708 BlockTagOp::create(builder, block->getParentOp()->getLoc(),
3709 BlockTagAttr::get(context, bb->getNumber()));
3710 }
3711 return success();
3712}
3713
3714FailureOr<SmallVector<AccessGroupAttr>>
3715ModuleImport::lookupAccessGroupAttrs(const llvm::MDNode *node) const {
3716 return loopAnnotationImporter->lookupAccessGroupAttrs(node);
3717}
3718
3719LoopAnnotationAttr
3721 Location loc) const {
3722 return loopAnnotationImporter->translateLoopAnnotation(node, loc);
3723}
3724
3725FailureOr<DereferenceableAttr>
3727 unsigned kindID) {
3728 Location loc = mlirModule.getLoc();
3729
3730 // The only operand should be a constant integer representing the number of
3731 // dereferenceable bytes.
3732 if (node->getNumOperands() != 1)
3733 return emitError(loc) << "dereferenceable metadata must have one operand: "
3734 << diagMD(node, llvmModule.get());
3735
3736 auto *numBytesMD = dyn_cast<llvm::ConstantAsMetadata>(node->getOperand(0));
3737 auto *numBytesCst = dyn_cast<llvm::ConstantInt>(numBytesMD->getValue());
3738 if (!numBytesCst || !numBytesCst->getValue().isNonNegative())
3739 return emitError(loc) << "dereferenceable metadata operand must be a "
3740 "non-negative constant integer: "
3741 << diagMD(node, llvmModule.get());
3742
3743 bool mayBeNull = kindID == llvm::LLVMContext::MD_dereferenceable_or_null;
3744 auto derefAttr = builder.getAttr<DereferenceableAttr>(
3745 numBytesCst->getZExtValue(), mayBeNull);
3746
3747 return derefAttr;
3748}
3749
3751 std::unique_ptr<llvm::Module> llvmModule, MLIRContext *context,
3752 bool emitExpensiveWarnings, bool dropDICompositeTypeElements,
3753 bool loadAllDialects, bool preferUnregisteredIntrinsics,
3754 bool importStructsAsLiterals) {
3755 // Preload all registered dialects to allow the import to iterate the
3756 // registered LLVMImportDialectInterface implementations and query the
3757 // supported LLVM IR constructs before starting the translation. Assumes the
3758 // LLVM and DLTI dialects that convert the core LLVM IR constructs have been
3759 // registered before.
3760 assert(llvm::is_contained(context->getAvailableDialects(),
3761 LLVMDialect::getDialectNamespace()));
3762 assert(llvm::is_contained(context->getAvailableDialects(),
3763 DLTIDialect::getDialectNamespace()));
3764 if (loadAllDialects)
3765 context->loadAllAvailableDialects();
3766 OwningOpRef<ModuleOp> module(ModuleOp::create(FileLineColLoc::get(
3767 StringAttr::get(context, llvmModule->getSourceFileName()), /*line=*/0,
3768 /*column=*/0)));
3769
3770 ModuleImport moduleImport(module.get(), std::move(llvmModule),
3771 emitExpensiveWarnings, dropDICompositeTypeElements,
3772 preferUnregisteredIntrinsics,
3773 importStructsAsLiterals);
3774 if (failed(moduleImport.initializeImportInterface()))
3775 return {};
3776 if (failed(moduleImport.convertDataLayout()))
3777 return {};
3778 if (failed(moduleImport.convertComdats()))
3779 return {};
3780 if (failed(moduleImport.convertMetadata()))
3781 return {};
3782 if (failed(moduleImport.convertGlobals()))
3783 return {};
3784 if (failed(moduleImport.convertFunctions()))
3785 return {};
3786 if (failed(moduleImport.convertAliases()))
3787 return {};
3788 if (failed(moduleImport.convertIFuncs()))
3789 return {};
3790 moduleImport.convertTargetTriple();
3791 moduleImport.convertModuleLevelAsm();
3792 return module;
3793}
return success()
ArrayAttr()
b getContext())
*if copies could not be generated due to yet unimplemented cases *copyInPlacementStart and copyOutPlacementStart in copyPlacementBlock *specify the insertion points where the incoming copies and outgoing should be inserted(the insertion happens right before the *insertion point). Since `begin` can itself be invalidated due to the memref *rewriting done from this method
static ArrayAttr convertLLVMAttributesToMLIR(Location loc, MLIRContext *context, llvm::AttributeSet attributes, ArrayRef< StringLiteral > attributesToSkip={}, ArrayRef< StringLiteral > attributePrefixesToSkip={})
Converts LLVM string, integer, and enum attributes into MLIR attributes, skipping those in attributes...
static StringRef getLLVMSyncScope(llvm::Instruction *inst)
Converts the sync scope identifier of inst to the string representation necessary to build an atomic ...
static std::string diag(const llvm::Value &value)
static void processPassthroughAttrs(llvm::Function *func, LLVMFuncOp funcOp)
Converts LLVM attributes from func into MLIR attributes and adds them to funcOp as passthrough attrib...
static SmallVector< Attribute > getSequenceConstantAsAttrs(OpBuilder &builder, llvm::ConstantDataSequential *constSequence)
Returns an integer or float attribute array for the provided constant sequence constSequence or nullp...
static LogicalResult convertCallBaseAttributes(llvm::CallBase *inst, Op op)
static void processMemoryEffects(llvm::Function *func, LLVMFuncOp funcOp)
static Attribute convertCGProfileModuleFlagValue(ModuleOp mlirModule, llvm::MDTuple *mdTuple)
static constexpr std::array kExplicitLLVMFuncOpAttributePrefixes
static constexpr StringRef getGlobalDtorsVarName()
Returns the name of the global_dtors global variables.
static Type getVectorTypeForAttr(Type type, ArrayRef< int64_t > arrayShape={})
Returns type if it is a builtin integer or floating-point vector type that can be used to create an a...
static LogicalResult convertInstructionImpl(OpBuilder &odsBuilder, llvm::Instruction *inst, ModuleImport &moduleImport, LLVMImportInterface &iface)
Converts the LLVM instructions that have a generated MLIR builder.
static constexpr StringRef getNamelessGlobalPrefix()
Prefix used for symbols of nameless llvm globals.
static Attribute convertModuleFlagValueFromMDTuple(ModuleOp mlirModule, const llvm::Module *llvmModule, StringRef key, llvm::MDTuple *mdTuple)
Invoke specific handlers for each known module flag value, returns nullptr if the key is unknown or u...
static constexpr std::array kExplicitLLVMFuncOpAttributes
static constexpr StringRef getGlobalComdatOpName()
Returns the symbol name for the module-level comdat operation.
static void convertNoBuiltinAttrs(MLIRContext *ctx, const llvm::AttributeSet &attrs, OpTy target)
static SmallVector< int64_t > getPositionFromIndices(ArrayRef< unsigned > indices)
Converts an array of unsigned indices to a signed integer position array.
static LogicalResult setDebugIntrinsicBuilderInsertionPoint(mlir::OpBuilder &builder, DominanceInfo &domInfo, Value argOperand)
Ensure that the debug intrinsic is inserted right after the operand definition.
static LogicalResult checkFunctionTypeCompatibility(LLVMFunctionType callType, LLVMFunctionType calleeType)
Checks if callType and calleeType are compatible and can be represented in MLIR.
static void processDenormalFPEnv(llvm::Function *func, LLVMFuncOp funcOp)
static std::optional< ProfileSummaryFormatKind > convertProfileSummaryFormat(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &formatMD)
static constexpr StringRef getGlobalCtorsVarName()
Returns the name of the global_ctors global variables.
static FailureOr< uint64_t > convertInt64FromKeyValueTuple(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &md, StringRef matchKey)
Extract an integer value from a two element tuple (<key, value>).
static void processTargetSpecificAttrs(llvm::GlobalVariable *globalVar, GlobalOp globalOp)
Converts LLVM attributes from globalVar into MLIR attributes and adds them to globalOp as target-spec...
static Attribute convertProfileSummaryModuleFlagValue(ModuleOp mlirModule, const llvm::Module *llvmModule, llvm::MDTuple *mdTuple)
static llvm::MDTuple * getTwoElementMDTuple(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &md)
Extract a two element MDTuple from a MDOperand.
static bool isMetadataKillLocation(llvm::DbgVariableIntrinsic *dbgIntr)
Checks if dbgIntr is a kill location that holds metadata instead of an SSA value.
static TypedAttr getScalarConstantAsAttr(OpBuilder &builder, llvm::Constant *constScalar)
Returns an integer or float attribute for the provided scalar constant constScalar or nullptr if the ...
static void convertAllocsizeAttr(MLIRContext *ctx, const llvm::AttributeSet &attrs, OpTy target)
static std::string diagMD(const llvm::Metadata *node, const llvm::Module *module)
static llvm::ConstantAsMetadata * getConstantMDFromKeyValueTuple(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &md, StringRef matchKey, bool optional=false)
Extract a constant metadata value from a two element tuple (<key, value>).
static FailureOr< SmallVector< ModuleFlagProfileSummaryDetailedAttr > > convertProfileSummaryDetailed(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &summaryMD)
static SetVector< llvm::BasicBlock * > getTopologicallySortedBlocks(ArrayRef< llvm::BasicBlock * > basicBlocks)
Get a topologically sorted list of blocks for the given basic blocks.
static llvm::ManagedStatic< PassManagerOptions > options
Attributes are known-constant values of operations.
Definition Attributes.h:25
This class represents an argument of a Block.
Definition Value.h:306
Block represents an ordered list of Operations.
Definition Block.h:33
bool empty()
Definition Block.h:172
Operation & front()
Definition Block.h:177
Operation * getTerminator()
Get the terminator operation of this block.
Definition Block.cpp:249
Operation * getParentOp()
Returns the closest surrounding operation that contains this block.
Definition Block.cpp:31
This class is a general helper class for creating context-global objects like types,...
Definition Builders.h:51
UnitAttr getUnitAttr()
Definition Builders.cpp:106
IntegerAttr getIntegerAttr(Type type, int64_t value)
Definition Builders.cpp:237
FloatAttr getFloatAttr(Type type, double value)
Definition Builders.cpp:263
IntegerAttr getI64IntegerAttr(int64_t value)
Definition Builders.cpp:120
StringAttr getStringAttr(const Twine &bytes)
Definition Builders.cpp:271
ArrayAttr getArrayAttr(ArrayRef< Attribute > value)
Definition Builders.cpp:275
MLIRContext * getContext() const
Definition Builders.h:56
NamedAttribute getNamedAttr(StringRef name, Attribute val)
Definition Builders.cpp:102
Attr getAttr(Args &&...args)
Get or construct an instance of the attribute Attr with provided arguments.
Definition Builders.h:101
static DenseElementsAttr get(ShapedType type, ArrayRef< Attribute > values)
Constructs a dense elements attribute from an array of element values.
static DistinctAttr create(Attribute referencedAttr)
Creates a distinct attribute that associates a referenced attribute with a unique identifier.
A class for computing basic dominance information.
Definition Dominance.h:143
static FileLineColLoc get(StringAttr filename, unsigned line, unsigned column)
Definition Location.cpp:157
A symbol reference with a reference path containing a single element.
static FlatSymbolRefAttr get(StringAttr value)
Construct a symbol reference for the given value name.
StringRef getValue() const
Returns the name of the held symbol reference.
Interface collection for the import of LLVM IR that dispatches to a concrete dialect interface implem...
LogicalResult convertInstruction(OpBuilder &builder, llvm::Instruction *inst, ArrayRef< llvm::Value * > llvmOperands, LLVM::ModuleImport &moduleImport) const
Converts the LLVM instruction to an MLIR operation if a conversion exists.
LogicalResult setMetadataAttrs(OpBuilder &builder, unsigned kind, llvm::MDNode *node, Operation *op, LLVM::ModuleImport &moduleImport) const
Attaches the given LLVM metadata to the imported operation if a conversion to one or more MLIR dialec...
bool isConvertibleMetadata(unsigned kind)
Returns true if the given LLVM IR metadata is convertible to an MLIR attribute.
bool isConvertibleInstruction(unsigned id)
Returns true if the given LLVM IR instruction is convertible to an MLIR operation.
Module import implementation class that provides methods to import globals and functions from an LLVM...
LogicalResult convertIFuncs()
Converts all ifuncs of the LLVM module to MLIR variables.
LogicalResult convertIntrinsicArguments(ArrayRef< llvm::Value * > values, ArrayRef< llvm::OperandBundleUse > opBundles, bool requiresOpBundles, ArrayRef< unsigned > immArgPositions, ArrayRef< StringLiteral > immArgAttrNames, SmallVectorImpl< Value > &valuesOut, SmallVectorImpl< NamedAttribute > &attrsOut)
Converts the LLVM values for an intrinsic to mixed MLIR values and attributes for LLVM_IntrOpBase.
Location translateLoc(llvm::DILocation *loc)
Translates the debug location.
LogicalResult convertComdats()
Converts all comdat selectors of the LLVM module to MLIR comdat operations.
LogicalResult convertAliases()
Converts all aliases of the LLVM module to MLIR variables.
LogicalResult convertFunctions()
Converts all functions of the LLVM module to MLIR functions.
FailureOr< SmallVector< Value > > convertValues(ArrayRef< llvm::Value * > values)
Converts a range of LLVM values to a range of MLIR values using the convertValue method,...
LogicalResult convertLinkerOptionsMetadata()
Converts !llvm.linker.options metadata to the llvm.linker.options LLVM dialect operation.
Block * lookupBlock(llvm::BasicBlock *block) const
Returns the MLIR block mapped to the given LLVM block.
void mapBlock(llvm::BasicBlock *llvm, Block *mlir)
Stores the mapping between an LLVM block and its MLIR counterpart.
DILocalVariableAttr matchLocalVariableAttr(llvm::PointerUnion< llvm::Value *, llvm::DILocalVariable * > valOrVariable)
Converts valOrVariable to a local variable attribute.
void processFunctionAttributes(llvm::Function *func, LLVMFuncOp funcOp)
Converts function attributes of LLVM Function func into LLVM dialect attributes of LLVMFuncOp funcOp.
LogicalResult convertMetadata()
Converts all LLVM metadata nodes that translate to attributes such as alias analysis or access group ...
FailureOr< Value > convertValue(llvm::Value *value)
Converts an LLVM value to an MLIR value, or returns failure if the conversion fails.
LogicalResult initializeImportInterface()
Calls the LLVMImportInterface initialization that queries the registered dialect interfaces for the s...
void addDebugIntrinsic(llvm::CallInst *intrinsic)
Adds a debug intrinsics to the list of intrinsics that should be converted after the function convers...
LogicalResult convertIdentMetadata()
Converts !llvm.ident metadata to the llvm.ident LLVM ModuleOp attribute.
FailureOr< Value > convertMetadataValue(llvm::Value *value)
Converts an LLVM metadata value to an MLIR value, or returns failure if the conversion fails.
FailureOr< SmallVector< AliasScopeAttr > > lookupAliasScopeAttrs(const llvm::MDNode *node) const
Returns the alias scope attributes that map to the alias scope nodes starting from the metadata node.
void setDisjointFlag(llvm::Instruction *inst, Operation *op) const
Sets the disjoint flag attribute for the imported operation op given the original instruction inst.
void mapNoResultOp(llvm::Instruction *llvm, Operation *mlir)
Stores a mapping between an LLVM instruction and the imported MLIR operation if the operation returns...
void convertModuleLevelAsm()
Converts the module level asm of the LLVM module to an MLIR module level asm specification.
void setExactFlag(llvm::Instruction *inst, Operation *op) const
Sets the exact flag attribute for the imported operation op given the original instruction inst.
Type convertType(llvm::Type *type)
Converts the type from LLVM to MLIR LLVM dialect.
ModuleImport(ModuleOp mlirModule, std::unique_ptr< llvm::Module > llvmModule, bool emitExpensiveWarnings, bool importEmptyDICompositeTypes, bool preferUnregisteredIntrinsics, bool importStructsAsLiterals)
DILabelAttr matchLabelAttr(llvm::Value *value)
Converts value to a label attribute. Asserts if the matching fails.
FloatAttr matchFloatAttr(llvm::Value *value)
Converts value to a float attribute. Asserts if the matching fails.
LoopAnnotationAttr translateLoopAnnotationAttr(const llvm::MDNode *node, Location loc) const
Returns the loop annotation attribute that corresponds to the given LLVM loop metadata node.
void setFastmathFlagsAttr(llvm::Instruction *inst, Operation *op) const
Sets the fastmath flags attribute for the imported operation op given the original instruction inst.
FailureOr< SmallVector< AliasScopeAttr > > matchAliasScopeAttrs(llvm::Value *value)
Converts value to an array of alias scopes or returns failure if the conversion fails.
Value lookupValue(llvm::Value *value)
Returns the MLIR value mapped to the given LLVM value.
Operation * lookupOperation(llvm::Instruction *inst)
Returns the MLIR operation mapped to the given LLVM instruction.
LogicalResult processFunction(llvm::Function *func)
Imports func into the current module.
LogicalResult convertDependentLibrariesMetadata()
Converts !llvm.dependent-libraries metadata to llvm.dependent_libraries LLVM ModuleOp attribute.
RoundingModeAttr matchRoundingModeAttr(llvm::Value *value)
Converts value to a rounding mode attribute.
void convertTargetTriple()
Converts target triple of the LLVM module to an MLIR target triple specification.
void addDebugRecord(llvm::DbgVariableRecord *dbgRecord)
Adds a debug record to the list of debug records that need to be imported after the function conversi...
void convertArgAndResultAttrs(llvm::CallBase *call, ArgAndResultAttrsOpInterface attrsOp, ArrayRef< unsigned > immArgPositions={})
Converts the argument and result attributes attached to call and adds them to attrsOp.
LogicalResult convertModuleFlagsMetadata()
Converts !llvm.module.flags metadata.
void mapValue(llvm::Value *llvm, Value mlir)
Stores the mapping between an LLVM value and its MLIR counterpart.
FailureOr< SmallVector< AccessGroupAttr > > lookupAccessGroupAttrs(const llvm::MDNode *node) const
Returns the access group attributes that map to the access group nodes starting from the access group...
LogicalResult convertGlobals()
Converts all global variables of the LLVM module to MLIR global variables.
void setIntegerOverflowFlags(llvm::Instruction *inst, Operation *op) const
Sets the integer overflow flags (nsw/nuw) attribute for the imported operation op given the original ...
LogicalResult convertCommandlineMetadata()
Converts !llvm.commandline metadata to the llvm.commandline LLVM ModuleOp attribute.
FPExceptionBehaviorAttr matchFPExceptionBehaviorAttr(llvm::Value *value)
Converts value to a FP exception behavior attribute.
void setNonNegFlag(llvm::Instruction *inst, Operation *op) const
Sets the nneg flag attribute for the imported operation op given the original instruction inst.
FailureOr< DereferenceableAttr > translateDereferenceableAttr(const llvm::MDNode *node, unsigned kindID)
Returns the dereferenceable attribute that corresponds to the given LLVM dereferenceable or dereferen...
LogicalResult convertDataLayout()
Converts the data layout of the LLVM module to an MLIR data layout specification.
IntegerAttr matchIntegerAttr(llvm::Value *value)
Converts value to an integer attribute. Asserts if the matching fails.
Helper class that translates an LLVM data layout string to an MLIR data layout specification.
StringRef getLastToken() const
Returns the last data layout token that has been processed before the data layout translation failed.
ArrayRef< StringRef > getUnhandledTokens() const
Returns the data layout tokens that have not been handled during the data layout translation.
DataLayoutSpecInterface getDataLayoutSpec() const
Returns the MLIR data layout specification translated from the LLVM data layout.
A helper class that converts llvm.loop metadata nodes into corresponding LoopAnnotationAttrs and llvm...
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition Location.h:76
MLIRContext is the top-level object for a collection of MLIR operations.
Definition MLIRContext.h:63
std::vector< StringRef > getAvailableDialects()
Return information about all available dialects in the registry in this context.
void loadAllAvailableDialects()
Load all dialects available in the registry in this context.
RAII guard to reset the insertion point of the builder when destroyed.
Definition Builders.h:351
This class helps build Operations.
Definition Builders.h:210
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
Definition Builders.h:401
void setInsertionPointToEnd(Block *block)
Sets the insertion point to the end of the specified block.
Definition Builders.h:439
void setInsertionPointAfterValue(Value val)
Sets the insertion point to the node after the specified value.
Definition Builders.h:424
This class provides the API for ops that are known to be terminators.
This provides public APIs that all operations should have.
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
Definition Operation.h:801
Location getLoc()
The source location the operation was defined or derived from.
Definition Operation.h:240
This class acts as an owning reference to an op, and will automatically destroy the held op on destru...
Definition OwningOpRef.h:29
OpTy get() const
Allow accessing the internal op.
Definition OwningOpRef.h:51
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition Region.h:26
iterator end()
Definition Region.h:56
static SmallString< N > generateSymbolName(StringRef name, UniqueChecker uniqueChecker, unsigned &uniquingCounter)
Generate a unique symbol name.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
MLIRContext * getContext() const
Return the MLIRContext in which this type was uniqued.
Definition Types.cpp:35
bool isIntOrFloat() const
Return true if this is an integer (of any signedness) or a float type.
Definition Types.cpp:118
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
Block * getParentBlock()
Return the Block in which this Value is defined.
Definition Value.cpp:46
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
Definition Value.cpp:18
static DenseArrayAttrImpl get(MLIRContext *context, ArrayRef< int32_t > content)
DominanceInfoNode * getNode(Block *a)
Return the dominance node from the Region containing block A.
Definition Dominance.h:85
static llvm::ArrayRef< std::pair< llvm::Attribute::AttrKind, llvm::StringRef > > getAttrKindToNameMapping()
Returns a list of pairs that each hold a mapping from LLVM attribute kinds to their corresponding str...
FloatType getFloatType(MLIRContext *context, unsigned width)
Returns a supported MLIR floating point type of the given bit width or null if the bit width is not s...
bool isCompatibleVectorType(Type type)
Returns true if the given type is a vector type compatible with the LLVM dialect.
llvm::ElementCount getVectorNumElements(Type type)
Returns the element count of any LLVM-compatible vector type.
detail::InFlightRemark failed(Location loc, RemarkOpts opts)
Report an optimization remark that failed.
Definition Remarks.h:717
Include the generated interface declarations.
bool matchPattern(Value value, const Pattern &pattern)
Entry point for matching a pattern over a Value.
Definition Matchers.h:490
InFlightDiagnostic emitWarning(Location loc)
Utility method to emit a warning message using this location.
llvm::DenseSet< ValueT, ValueInfoT > DenseSet
Definition LLVM.h:122
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
llvm::SetVector< T, Vector, Set, N > SetVector
Definition LLVM.h:125
llvm::DenseMap< KeyT, ValueT, KeyInfoT, BucketT > DenseMap
Definition LLVM.h:120
detail::constant_op_matcher m_Constant()
Matches a constant foldable operation.
Definition Matchers.h:369
OwningOpRef< ModuleOp > translateLLVMIRToModule(std::unique_ptr< llvm::Module > llvmModule, MLIRContext *context, bool emitExpensiveWarnings=true, bool dropDICompositeTypeElements=false, bool loadAllDialects=true, bool preferUnregisteredIntrinsics=false, bool importStructsAsLiterals=false)
Translates the LLVM module into an MLIR module living in the given context.