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