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