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