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 intergers.
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 aggregate constants.
1769 if (isa<llvm::ConstantAggregate>(constant) ||
1770 isa<llvm::ConstantAggregateZero>(constant)) {
1771 // Lookup the aggregate elements that have been converted before.
1772 SmallVector<Value> elementValues;
1773 if (auto *constAgg = dyn_cast<llvm::ConstantAggregate>(constant)) {
1774 elementValues.reserve(constAgg->getNumOperands());
1775 for (llvm::Value *operand : constAgg->operands())
1776 elementValues.push_back(lookupValue(operand));
1777 }
1778 if (auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1779 unsigned numElements = constAgg->getElementCount().getFixedValue();
1780 elementValues.reserve(numElements);
1781 for (unsigned i = 0, e = numElements; i != e; ++i)
1782 elementValues.push_back(lookupValue(constAgg->getElementValue(i)));
1783 }
1784 assert(llvm::count(elementValues, nullptr) == 0 &&
1785 "expected all elements have been converted before");
1786
1787 // Generate an UndefOp as root value and insert the aggregate elements.
1788 Type rootType = convertType(constant->getType());
1789 bool isArrayOrStruct = isa<LLVMArrayType, LLVMStructType>(rootType);
1790 assert((isArrayOrStruct || LLVM::isCompatibleVectorType(rootType)) &&
1791 "unrecognized aggregate type");
1792 Value root = UndefOp::create(builder, loc, rootType);
1793 for (const auto &it : llvm::enumerate(elementValues)) {
1794 if (isArrayOrStruct) {
1795 root =
1796 InsertValueOp::create(builder, loc, root, it.value(), it.index());
1797 } else {
1798 Attribute indexAttr = builder.getI32IntegerAttr(it.index());
1799 Value indexValue =
1800 ConstantOp::create(builder, loc, builder.getI32Type(), indexAttr);
1801 root = InsertElementOp::create(builder, loc, rootType, root, it.value(),
1802 indexValue);
1803 }
1804 }
1805 return root;
1806 }
1807
1808 if (auto *constTargetNone = dyn_cast<llvm::ConstantTargetNone>(constant)) {
1809 LLVMTargetExtType targetExtType =
1810 cast<LLVMTargetExtType>(convertType(constTargetNone->getType()));
1811 assert(targetExtType.hasProperty(LLVMTargetExtType::HasZeroInit) &&
1812 "target extension type does not support zero-initialization");
1813 // Create llvm.mlir.zero operation to represent zero-initialization of
1814 // target extension type.
1815 return LLVM::ZeroOp::create(builder, loc, targetExtType).getRes();
1816 }
1817
1818 if (auto *blockAddr = dyn_cast<llvm::BlockAddress>(constant)) {
1819 auto fnSym =
1820 FlatSymbolRefAttr::get(context, blockAddr->getFunction()->getName());
1821 auto blockTag =
1822 BlockTagAttr::get(context, blockAddr->getBasicBlock()->getNumber());
1823 return BlockAddressOp::create(
1824 builder, loc, convertType(blockAddr->getType()),
1825 BlockAddressAttr::get(context, fnSym, blockTag))
1826 .getRes();
1827 }
1828
1829 StringRef error = "";
1830
1831 if (isa<llvm::ConstantPtrAuth>(constant))
1832 error = " since ptrauth(...) is unsupported";
1833
1834 if (isa<llvm::NoCFIValue>(constant))
1835 error = " since no_cfi is unsupported";
1836
1837 if (isa<llvm::GlobalValue>(constant))
1838 error = " since global value is unsupported";
1839
1840 return emitError(loc) << "unhandled constant: " << diag(*constant) << error;
1841}
1842
1843FailureOr<Value> ModuleImport::convertConstantExpr(llvm::Constant *constant) {
1844 // Only call the function for constants that have not been translated before
1845 // since it updates the constant insertion point assuming the converted
1846 // constant has been introduced at the end of the constant section.
1847 assert(!valueMapping.contains(constant) &&
1848 "expected constant has not been converted before");
1849 assert(constantInsertionBlock &&
1850 "expected the constant insertion block to be non-null");
1851
1852 // Insert the constant after the last one or at the start of the entry block.
1853 OpBuilder::InsertionGuard guard(builder);
1854 if (!constantInsertionOp)
1855 builder.setInsertionPointToStart(constantInsertionBlock);
1856 else
1857 builder.setInsertionPointAfter(constantInsertionOp);
1858
1859 // Convert all constants of the expression and add them to `valueMapping`.
1860 SetVector<llvm::Constant *> constantsToConvert =
1861 getConstantsToConvert(constant);
1862 for (llvm::Constant *constantToConvert : constantsToConvert) {
1863 FailureOr<Value> converted = convertConstant(constantToConvert);
1864 if (failed(converted))
1865 return failure();
1866 mapValue(constantToConvert, *converted);
1867 }
1868
1869 // Update the constant insertion point and return the converted constant.
1870 Value result = lookupValue(constant);
1871 constantInsertionOp = result.getDefiningOp();
1872 return result;
1873}
1874
1875FailureOr<Value> ModuleImport::convertValue(llvm::Value *value) {
1876 assert(!isa<llvm::MetadataAsValue>(value) &&
1877 "expected value to not be metadata");
1878
1879 // Return the mapped value if it has been converted before.
1880 auto it = valueMapping.find(value);
1881 if (it != valueMapping.end())
1882 return it->getSecond();
1883
1884 // Convert constants such as immediate values that have no mapping yet.
1885 if (auto *constant = dyn_cast<llvm::Constant>(value))
1886 return convertConstantExpr(constant);
1887
1888 Location loc = UnknownLoc::get(context);
1889 if (auto *inst = dyn_cast<llvm::Instruction>(value))
1890 loc = translateLoc(inst->getDebugLoc());
1891 return emitError(loc) << "unhandled value: " << diag(*value);
1892}
1893
1894FailureOr<Value> ModuleImport::convertMetadataValue(llvm::Value *value) {
1895 // A value may be wrapped as metadata, for example, when passed to a debug
1896 // intrinsic. Unwrap these values before the conversion.
1897 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
1898 if (!nodeAsVal)
1899 return failure();
1900 auto *node = dyn_cast<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
1901 if (!node)
1902 return failure();
1903 value = node->getValue();
1904
1905 // Return the mapped value if it has been converted before.
1906 auto it = valueMapping.find(value);
1907 if (it != valueMapping.end())
1908 return it->getSecond();
1909
1910 // Convert constants such as immediate values that have no mapping yet.
1911 if (auto *constant = dyn_cast<llvm::Constant>(value))
1912 return convertConstantExpr(constant);
1913 return failure();
1914}
1915
1916FailureOr<SmallVector<Value>>
1918 SmallVector<Value> remapped;
1919 remapped.reserve(values.size());
1920 for (llvm::Value *value : values) {
1921 FailureOr<Value> converted = convertValue(value);
1922 if (failed(converted))
1923 return failure();
1924 remapped.push_back(*converted);
1925 }
1926 return remapped;
1927}
1928
1931 bool requiresOpBundles, ArrayRef<unsigned> immArgPositions,
1932 ArrayRef<StringLiteral> immArgAttrNames, SmallVectorImpl<Value> &valuesOut,
1934 assert(immArgPositions.size() == immArgAttrNames.size() &&
1935 "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "
1936 "length");
1937
1938 SmallVector<llvm::Value *> operands(values);
1939 for (auto [immArgPos, immArgName] :
1940 llvm::zip(immArgPositions, immArgAttrNames)) {
1941 auto &value = operands[immArgPos];
1942 auto *constant = llvm::cast<llvm::Constant>(value);
1943 auto attr = getScalarConstantAsAttr(builder, constant);
1944 assert(attr && attr.getType().isIntOrFloat() &&
1945 "expected immarg to be float or integer constant");
1946 auto nameAttr = StringAttr::get(attr.getContext(), immArgName);
1947 attrsOut.push_back({nameAttr, attr});
1948 // Mark matched attribute values as null (so they can be removed below).
1949 value = nullptr;
1950 }
1951
1952 for (llvm::Value *value : operands) {
1953 if (!value)
1954 continue;
1955 auto mlirValue = convertValue(value);
1956 if (failed(mlirValue))
1957 return failure();
1958 valuesOut.push_back(*mlirValue);
1959 }
1960
1961 SmallVector<int> opBundleSizes;
1962 SmallVector<Attribute> opBundleTagAttrs;
1963 if (requiresOpBundles) {
1964 opBundleSizes.reserve(opBundles.size());
1965 opBundleTagAttrs.reserve(opBundles.size());
1966
1967 for (const llvm::OperandBundleUse &bundle : opBundles) {
1968 opBundleSizes.push_back(bundle.Inputs.size());
1969 opBundleTagAttrs.push_back(StringAttr::get(context, bundle.getTagName()));
1970
1971 for (const llvm::Use &opBundleOperand : bundle.Inputs) {
1972 auto operandMlirValue = convertValue(opBundleOperand.get());
1973 if (failed(operandMlirValue))
1974 return failure();
1975 valuesOut.push_back(*operandMlirValue);
1976 }
1977 }
1978
1979 auto opBundleSizesAttr = DenseI32ArrayAttr::get(context, opBundleSizes);
1980 auto opBundleSizesAttrNameAttr =
1981 StringAttr::get(context, LLVMDialect::getOpBundleSizesAttrName());
1982 attrsOut.push_back({opBundleSizesAttrNameAttr, opBundleSizesAttr});
1983
1984 auto opBundleTagsAttr = ArrayAttr::get(context, opBundleTagAttrs);
1985 auto opBundleTagsAttrNameAttr =
1986 StringAttr::get(context, LLVMDialect::getOpBundleTagsAttrName());
1987 attrsOut.push_back({opBundleTagsAttrNameAttr, opBundleTagsAttr});
1988 }
1989
1990 return success();
1991}
1992
1993IntegerAttr ModuleImport::matchIntegerAttr(llvm::Value *value) {
1994 IntegerAttr integerAttr;
1995 FailureOr<Value> converted = convertValue(value);
1996 bool success = succeeded(converted) &&
1997 matchPattern(*converted, m_Constant(&integerAttr));
1998 assert(success && "expected a constant integer value");
1999 (void)success;
2000 return integerAttr;
2001}
2002
2003FloatAttr ModuleImport::matchFloatAttr(llvm::Value *value) {
2004 FloatAttr floatAttr;
2005 FailureOr<Value> converted = convertValue(value);
2006 bool success =
2007 succeeded(converted) && matchPattern(*converted, m_Constant(&floatAttr));
2008 assert(success && "expected a constant float value");
2009 (void)success;
2010 return floatAttr;
2011}
2012
2015 llvm::DILocalVariable *node = nullptr;
2016 if (auto *value = dyn_cast<llvm::Value *>(valOrVariable)) {
2017 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2018 node = cast<llvm::DILocalVariable>(nodeAsVal->getMetadata());
2019 } else {
2020 node = cast<llvm::DILocalVariable *>(valOrVariable);
2021 }
2022 return debugImporter->translate(node);
2023}
2024
2025DILabelAttr ModuleImport::matchLabelAttr(llvm::Value *value) {
2026 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2027 auto *node = cast<llvm::DILabel>(nodeAsVal->getMetadata());
2028 return debugImporter->translate(node);
2029}
2030
2031FPExceptionBehaviorAttr
2033 auto *metadata = cast<llvm::MetadataAsValue>(value);
2034 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
2035 std::optional<llvm::fp::ExceptionBehavior> optLLVM =
2036 llvm::convertStrToExceptionBehavior(mdstr->getString());
2037 assert(optLLVM && "Expecting FP exception behavior");
2038 return builder.getAttr<FPExceptionBehaviorAttr>(
2039 convertFPExceptionBehaviorFromLLVM(*optLLVM));
2040}
2041
2042RoundingModeAttr ModuleImport::matchRoundingModeAttr(llvm::Value *value) {
2043 auto *metadata = cast<llvm::MetadataAsValue>(value);
2044 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
2045 std::optional<llvm::RoundingMode> optLLVM =
2046 llvm::convertStrToRoundingMode(mdstr->getString());
2047 assert(optLLVM && "Expecting rounding mode");
2048 return builder.getAttr<RoundingModeAttr>(
2049 convertRoundingModeFromLLVM(*optLLVM));
2050}
2051
2052FailureOr<SmallVector<AliasScopeAttr>>
2054 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2055 auto *node = cast<llvm::MDNode>(nodeAsVal->getMetadata());
2056 return lookupAliasScopeAttrs(node);
2057}
2058
2059Location ModuleImport::translateLoc(llvm::DILocation *loc) {
2060 return debugImporter->translateLoc(loc);
2061}
2062
2063LogicalResult
2064ModuleImport::convertBranchArgs(llvm::Instruction *branch,
2065 llvm::BasicBlock *target,
2066 SmallVectorImpl<Value> &blockArguments) {
2067 for (auto inst = target->begin(); isa<llvm::PHINode>(inst); ++inst) {
2068 auto *phiInst = cast<llvm::PHINode>(&*inst);
2069 llvm::Value *value = phiInst->getIncomingValueForBlock(branch->getParent());
2070 FailureOr<Value> converted = convertValue(value);
2071 if (failed(converted))
2072 return failure();
2073 blockArguments.push_back(*converted);
2074 }
2075 return success();
2076}
2077
2078FailureOr<SmallVector<Value>>
2079ModuleImport::convertCallOperands(llvm::CallBase *callInst,
2080 bool allowInlineAsm) {
2081 bool isInlineAsm = callInst->isInlineAsm();
2082 if (isInlineAsm && !allowInlineAsm)
2083 return failure();
2084
2085 SmallVector<Value> operands;
2086
2087 // Cannot use isIndirectCall() here because we need to handle Constant callees
2088 // that are not considered indirect calls by LLVM. However, in MLIR, they are
2089 // treated as indirect calls to constant operands that need to be converted.
2090 // Skip the callee operand if it's inline assembly, as it's handled separately
2091 // in InlineAsmOp.
2092 llvm::Value *calleeOperand = callInst->getCalledOperand();
2093 if (!isa<llvm::Function, llvm::GlobalIFunc>(calleeOperand) && !isInlineAsm) {
2094 FailureOr<Value> called = convertValue(calleeOperand);
2095 if (failed(called))
2096 return failure();
2097 operands.push_back(*called);
2098 }
2099
2100 SmallVector<llvm::Value *> args(callInst->args());
2101 FailureOr<SmallVector<Value>> arguments = convertValues(args);
2102 if (failed(arguments))
2103 return failure();
2104
2105 llvm::append_range(operands, *arguments);
2106 return operands;
2107}
2108
2109/// Checks if `callType` and `calleeType` are compatible and can be represented
2110/// in MLIR.
2111static LogicalResult
2112checkFunctionTypeCompatibility(LLVMFunctionType callType,
2113 LLVMFunctionType calleeType) {
2114 if (callType.getReturnType() != calleeType.getReturnType())
2115 return failure();
2116
2117 if (calleeType.isVarArg()) {
2118 // For variadic functions, the call can have more types than the callee
2119 // specifies.
2120 if (callType.getNumParams() < calleeType.getNumParams())
2121 return failure();
2122 } else {
2123 // For non-variadic functions, the number of parameters needs to be the
2124 // same.
2125 if (callType.getNumParams() != calleeType.getNumParams())
2126 return failure();
2127 }
2128
2129 // Check that all operands match.
2130 for (auto [operandType, argumentType] :
2131 llvm::zip(callType.getParams(), calleeType.getParams()))
2132 if (operandType != argumentType)
2133 return failure();
2134
2135 return success();
2136}
2137
2138FailureOr<LLVMFunctionType>
2139ModuleImport::convertFunctionType(llvm::CallBase *callInst,
2140 bool &isIncompatibleCall) {
2141 isIncompatibleCall = false;
2142 auto castOrFailure = [](Type convertedType) -> FailureOr<LLVMFunctionType> {
2143 auto funcTy = dyn_cast_or_null<LLVMFunctionType>(convertedType);
2144 if (!funcTy)
2145 return failure();
2146 return funcTy;
2147 };
2148
2149 llvm::Value *calledOperand = callInst->getCalledOperand();
2150 FailureOr<LLVMFunctionType> callType =
2151 castOrFailure(convertType(callInst->getFunctionType()));
2152 if (failed(callType))
2153 return failure();
2154 auto *callee = dyn_cast<llvm::Function>(calledOperand);
2155
2156 llvm::FunctionType *origCalleeType = nullptr;
2157 if (callee) {
2158 origCalleeType = callee->getFunctionType();
2159 } else if (auto *ifunc = dyn_cast<llvm::GlobalIFunc>(calledOperand)) {
2160 origCalleeType = cast<llvm::FunctionType>(ifunc->getValueType());
2161 }
2162
2163 // For indirect calls, return the type of the call itself.
2164 if (!origCalleeType)
2165 return callType;
2166
2167 FailureOr<LLVMFunctionType> calleeType =
2168 castOrFailure(convertType(origCalleeType));
2169 if (failed(calleeType))
2170 return failure();
2171
2172 // Compare the types and notify users via `isIncompatibleCall` if they are not
2173 // compatible.
2174 if (failed(checkFunctionTypeCompatibility(*callType, *calleeType))) {
2175 isIncompatibleCall = true;
2176 Location loc = translateLoc(callInst->getDebugLoc());
2177 emitWarning(loc) << "incompatible call and callee types: " << *callType
2178 << " and " << *calleeType;
2179 return callType;
2180 }
2181
2182 return calleeType;
2183}
2184
2185FlatSymbolRefAttr ModuleImport::convertCalleeName(llvm::CallBase *callInst) {
2186 llvm::Value *calledOperand = callInst->getCalledOperand();
2187 if (isa<llvm::Function, llvm::GlobalIFunc>(calledOperand))
2188 return SymbolRefAttr::get(context, calledOperand->getName());
2189 return {};
2190}
2191
2192LogicalResult ModuleImport::convertIntrinsic(llvm::CallInst *inst) {
2193 if (succeeded(iface.convertIntrinsic(builder, inst, *this)))
2194 return success();
2195
2196 Location loc = translateLoc(inst->getDebugLoc());
2197 return emitError(loc) << "unhandled intrinsic: " << diag(*inst);
2198}
2199
2201ModuleImport::convertAsmInlineOperandAttrs(const llvm::CallBase &llvmCall) {
2202 const auto *ia = cast<llvm::InlineAsm>(llvmCall.getCalledOperand());
2203 unsigned argIdx = 0;
2204 SmallVector<mlir::Attribute> opAttrs;
2205 bool hasIndirect = false;
2206
2207 for (const llvm::InlineAsm::ConstraintInfo &ci : ia->ParseConstraints()) {
2208 // Only deal with constraints that correspond to call arguments.
2209 if (ci.Type == llvm::InlineAsm::isLabel || !ci.hasArg())
2210 continue;
2211
2212 // Only increment `argIdx` in terms of constraints containing arguments,
2213 // which are guaranteed to happen in the same order of the call arguments.
2214 if (ci.isIndirect) {
2215 if (llvm::Type *paramEltType = llvmCall.getParamElementType(argIdx)) {
2216 SmallVector<mlir::NamedAttribute> attrs;
2217 attrs.push_back(builder.getNamedAttr(
2218 mlir::LLVM::InlineAsmOp::getElementTypeAttrName(),
2219 mlir::TypeAttr::get(convertType(paramEltType))));
2220 opAttrs.push_back(builder.getDictionaryAttr(attrs));
2221 hasIndirect = true;
2222 }
2223 } else {
2224 opAttrs.push_back(builder.getDictionaryAttr({}));
2225 }
2226 argIdx++;
2227 }
2228
2229 // Avoid emitting an array where all entries are empty dictionaries.
2230 return hasIndirect ? ArrayAttr::get(mlirModule->getContext(), opAttrs)
2231 : nullptr;
2232}
2233
2234LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
2235 // Convert all instructions that do not provide an MLIR builder.
2236 Location loc = translateLoc(inst->getDebugLoc());
2237 if (inst->getOpcode() == llvm::Instruction::Br) {
2238 auto *brInst = cast<llvm::BranchInst>(inst);
2239
2240 SmallVector<Block *> succBlocks;
2241 SmallVector<SmallVector<Value>> succBlockArgs;
2242 for (auto i : llvm::seq<unsigned>(0, brInst->getNumSuccessors())) {
2243 llvm::BasicBlock *succ = brInst->getSuccessor(i);
2244 SmallVector<Value> blockArgs;
2245 if (failed(convertBranchArgs(brInst, succ, blockArgs)))
2246 return failure();
2247 succBlocks.push_back(lookupBlock(succ));
2248 succBlockArgs.push_back(blockArgs);
2249 }
2250
2251 if (!brInst->isConditional()) {
2252 auto brOp = LLVM::BrOp::create(builder, loc, succBlockArgs.front(),
2253 succBlocks.front());
2254 mapNoResultOp(inst, brOp);
2255 return success();
2256 }
2257 FailureOr<Value> condition = convertValue(brInst->getCondition());
2258 if (failed(condition))
2259 return failure();
2260 auto condBrOp = LLVM::CondBrOp::create(
2261 builder, loc, *condition, succBlocks.front(), succBlockArgs.front(),
2262 succBlocks.back(), succBlockArgs.back());
2263 mapNoResultOp(inst, condBrOp);
2264 return success();
2265 }
2266 if (inst->getOpcode() == llvm::Instruction::Switch) {
2267 auto *swInst = cast<llvm::SwitchInst>(inst);
2268 // Process the condition value.
2269 FailureOr<Value> condition = convertValue(swInst->getCondition());
2270 if (failed(condition))
2271 return failure();
2272 SmallVector<Value> defaultBlockArgs;
2273 // Process the default case.
2274 llvm::BasicBlock *defaultBB = swInst->getDefaultDest();
2275 if (failed(convertBranchArgs(swInst, defaultBB, defaultBlockArgs)))
2276 return failure();
2277
2278 // Process the cases.
2279 unsigned numCases = swInst->getNumCases();
2280 SmallVector<SmallVector<Value>> caseOperands(numCases);
2281 SmallVector<ValueRange> caseOperandRefs(numCases);
2282 SmallVector<APInt> caseValues(numCases);
2283 SmallVector<Block *> caseBlocks(numCases);
2284 for (const auto &it : llvm::enumerate(swInst->cases())) {
2285 const llvm::SwitchInst::CaseHandle &caseHandle = it.value();
2286 llvm::BasicBlock *succBB = caseHandle.getCaseSuccessor();
2287 if (failed(convertBranchArgs(swInst, succBB, caseOperands[it.index()])))
2288 return failure();
2289 caseOperandRefs[it.index()] = caseOperands[it.index()];
2290 caseValues[it.index()] = caseHandle.getCaseValue()->getValue();
2291 caseBlocks[it.index()] = lookupBlock(succBB);
2292 }
2293
2294 auto switchOp = SwitchOp::create(builder, loc, *condition,
2295 lookupBlock(defaultBB), defaultBlockArgs,
2296 caseValues, caseBlocks, caseOperandRefs);
2297 mapNoResultOp(inst, switchOp);
2298 return success();
2299 }
2300 if (inst->getOpcode() == llvm::Instruction::PHI) {
2301 Type type = convertType(inst->getType());
2302 mapValue(inst, builder.getInsertionBlock()->addArgument(
2303 type, translateLoc(inst->getDebugLoc())));
2304 return success();
2305 }
2306 if (inst->getOpcode() == llvm::Instruction::Call) {
2307 auto *callInst = cast<llvm::CallInst>(inst);
2308 llvm::Value *calledOperand = callInst->getCalledOperand();
2309
2310 FailureOr<SmallVector<Value>> operands =
2311 convertCallOperands(callInst, /*allowInlineAsm=*/true);
2312 if (failed(operands))
2313 return failure();
2314
2315 auto callOp = [&]() -> FailureOr<Operation *> {
2316 if (auto *asmI = dyn_cast<llvm::InlineAsm>(calledOperand)) {
2317 Type resultTy = convertType(callInst->getType());
2318 if (!resultTy)
2319 return failure();
2320 ArrayAttr operandAttrs = convertAsmInlineOperandAttrs(*callInst);
2321 return InlineAsmOp::create(
2322 builder, loc, resultTy, *operands,
2323 builder.getStringAttr(asmI->getAsmString()),
2324 builder.getStringAttr(asmI->getConstraintString()),
2325 asmI->hasSideEffects(), asmI->isAlignStack(),
2326 convertTailCallKindFromLLVM(callInst->getTailCallKind()),
2327 AsmDialectAttr::get(
2328 mlirModule.getContext(),
2329 convertAsmDialectFromLLVM(asmI->getDialect())),
2330 operandAttrs)
2331 .getOperation();
2332 }
2333 bool isIncompatibleCall;
2334 FailureOr<LLVMFunctionType> funcTy =
2335 convertFunctionType(callInst, isIncompatibleCall);
2336 if (failed(funcTy))
2337 return failure();
2338
2339 FlatSymbolRefAttr callee = nullptr;
2340 if (isIncompatibleCall) {
2341 // Use an indirect call (in order to represent valid and verifiable LLVM
2342 // IR). Build the indirect call by passing an empty `callee` operand and
2343 // insert into `operands` to include the indirect call target.
2344 FlatSymbolRefAttr calleeSym = convertCalleeName(callInst);
2345 Value indirectCallVal = LLVM::AddressOfOp::create(
2346 builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);
2347 operands->insert(operands->begin(), indirectCallVal);
2348 } else {
2349 // Regular direct call using callee name.
2350 callee = convertCalleeName(callInst);
2351 }
2352 CallOp callOp = CallOp::create(builder, loc, *funcTy, callee, *operands);
2353
2354 if (failed(convertCallAttributes(callInst, callOp)))
2355 return failure();
2356
2357 // Handle parameter and result attributes unless it's an incompatible
2358 // call.
2359 if (!isIncompatibleCall)
2360 convertArgAndResultAttrs(callInst, callOp);
2361 return callOp.getOperation();
2362 }();
2363
2364 if (failed(callOp))
2365 return failure();
2366
2367 if (!callInst->getType()->isVoidTy())
2368 mapValue(inst, (*callOp)->getResult(0));
2369 else
2370 mapNoResultOp(inst, *callOp);
2371 return success();
2372 }
2373 if (inst->getOpcode() == llvm::Instruction::LandingPad) {
2374 auto *lpInst = cast<llvm::LandingPadInst>(inst);
2375
2376 SmallVector<Value> operands;
2377 operands.reserve(lpInst->getNumClauses());
2378 for (auto i : llvm::seq<unsigned>(0, lpInst->getNumClauses())) {
2379 FailureOr<Value> operand = convertValue(lpInst->getClause(i));
2380 if (failed(operand))
2381 return failure();
2382 operands.push_back(*operand);
2383 }
2384
2385 Type type = convertType(lpInst->getType());
2386 auto lpOp =
2387 LandingpadOp::create(builder, loc, type, lpInst->isCleanup(), operands);
2388 mapValue(inst, lpOp);
2389 return success();
2390 }
2391 if (inst->getOpcode() == llvm::Instruction::Invoke) {
2392 auto *invokeInst = cast<llvm::InvokeInst>(inst);
2393
2394 if (invokeInst->isInlineAsm())
2395 return emitError(loc) << "invoke of inline assembly is not supported";
2396
2397 FailureOr<SmallVector<Value>> operands = convertCallOperands(invokeInst);
2398 if (failed(operands))
2399 return failure();
2400
2401 // Check whether the invoke result is an argument to the normal destination
2402 // block.
2403 bool invokeResultUsedInPhi = llvm::any_of(
2404 invokeInst->getNormalDest()->phis(), [&](const llvm::PHINode &phi) {
2405 return phi.getIncomingValueForBlock(invokeInst->getParent()) ==
2406 invokeInst;
2407 });
2408
2409 Block *normalDest = lookupBlock(invokeInst->getNormalDest());
2410 Block *directNormalDest = normalDest;
2411 if (invokeResultUsedInPhi) {
2412 // The invoke result cannot be an argument to the normal destination
2413 // block, as that would imply using the invoke operation result in its
2414 // definition, so we need to create a dummy block to serve as an
2415 // intermediate destination.
2416 OpBuilder::InsertionGuard g(builder);
2417 directNormalDest = builder.createBlock(normalDest);
2418 }
2419
2420 SmallVector<Value> unwindArgs;
2421 if (failed(convertBranchArgs(invokeInst, invokeInst->getUnwindDest(),
2422 unwindArgs)))
2423 return failure();
2424
2425 bool isIncompatibleInvoke;
2426 FailureOr<LLVMFunctionType> funcTy =
2427 convertFunctionType(invokeInst, isIncompatibleInvoke);
2428 if (failed(funcTy))
2429 return failure();
2430
2431 FlatSymbolRefAttr calleeName = nullptr;
2432 if (isIncompatibleInvoke) {
2433 // Use an indirect invoke (in order to represent valid and verifiable LLVM
2434 // IR). Build the indirect invoke by passing an empty `callee` operand and
2435 // insert into `operands` to include the indirect invoke target.
2436 FlatSymbolRefAttr calleeSym = convertCalleeName(invokeInst);
2437 Value indirectInvokeVal = LLVM::AddressOfOp::create(
2438 builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);
2439 operands->insert(operands->begin(), indirectInvokeVal);
2440 } else {
2441 // Regular direct invoke using callee name.
2442 calleeName = convertCalleeName(invokeInst);
2443 }
2444 // Create the invoke operation. Normal destination block arguments will be
2445 // added later on to handle the case in which the operation result is
2446 // included in this list.
2447 auto invokeOp = InvokeOp::create(
2448 builder, loc, *funcTy, calleeName, *operands, directNormalDest,
2449 ValueRange(), lookupBlock(invokeInst->getUnwindDest()), unwindArgs);
2450
2451 if (failed(convertInvokeAttributes(invokeInst, invokeOp)))
2452 return failure();
2453
2454 // Handle parameter and result attributes unless it's an incompatible
2455 // invoke.
2456 if (!isIncompatibleInvoke)
2457 convertArgAndResultAttrs(invokeInst, invokeOp);
2458
2459 if (!invokeInst->getType()->isVoidTy())
2460 mapValue(inst, invokeOp.getResults().front());
2461 else
2462 mapNoResultOp(inst, invokeOp);
2463
2464 SmallVector<Value> normalArgs;
2465 if (failed(convertBranchArgs(invokeInst, invokeInst->getNormalDest(),
2466 normalArgs)))
2467 return failure();
2468
2469 if (invokeResultUsedInPhi) {
2470 // The dummy normal dest block will just host an unconditional branch
2471 // instruction to the normal destination block passing the required block
2472 // arguments (including the invoke operation's result).
2473 OpBuilder::InsertionGuard g(builder);
2474 builder.setInsertionPointToStart(directNormalDest);
2475 LLVM::BrOp::create(builder, loc, normalArgs, normalDest);
2476 } else {
2477 // If the invoke operation's result is not a block argument to the normal
2478 // destination block, just add the block arguments as usual.
2479 assert(llvm::none_of(
2480 normalArgs,
2481 [&](Value val) { return val.getDefiningOp() == invokeOp; }) &&
2482 "An llvm.invoke operation cannot pass its result as a block "
2483 "argument.");
2484 invokeOp.getNormalDestOperandsMutable().append(normalArgs);
2485 }
2486
2487 return success();
2488 }
2489 if (inst->getOpcode() == llvm::Instruction::GetElementPtr) {
2490 auto *gepInst = cast<llvm::GetElementPtrInst>(inst);
2491 Type sourceElementType = convertType(gepInst->getSourceElementType());
2492 FailureOr<Value> basePtr = convertValue(gepInst->getOperand(0));
2493 if (failed(basePtr))
2494 return failure();
2495
2496 // Treat every indices as dynamic since GEPOp::build will refine those
2497 // indices into static attributes later. One small downside of this
2498 // approach is that many unused `llvm.mlir.constant` would be emitted
2499 // at first place.
2500 SmallVector<GEPArg> indices;
2501 for (llvm::Value *operand : llvm::drop_begin(gepInst->operand_values())) {
2502 FailureOr<Value> index = convertValue(operand);
2503 if (failed(index))
2504 return failure();
2505 indices.push_back(*index);
2506 }
2507
2508 Type type = convertType(inst->getType());
2509 auto gepOp = GEPOp::create(
2510 builder, loc, type, sourceElementType, *basePtr, indices,
2511 static_cast<GEPNoWrapFlags>(gepInst->getNoWrapFlags().getRaw()));
2512 mapValue(inst, gepOp);
2513 return success();
2514 }
2515
2516 if (inst->getOpcode() == llvm::Instruction::IndirectBr) {
2517 auto *indBrInst = cast<llvm::IndirectBrInst>(inst);
2518
2519 FailureOr<Value> basePtr = convertValue(indBrInst->getAddress());
2520 if (failed(basePtr))
2521 return failure();
2522
2523 SmallVector<Block *> succBlocks;
2524 SmallVector<SmallVector<Value>> succBlockArgs;
2525 for (auto i : llvm::seq<unsigned>(0, indBrInst->getNumSuccessors())) {
2526 llvm::BasicBlock *succ = indBrInst->getSuccessor(i);
2527 SmallVector<Value> blockArgs;
2528 if (failed(convertBranchArgs(indBrInst, succ, blockArgs)))
2529 return failure();
2530 succBlocks.push_back(lookupBlock(succ));
2531 succBlockArgs.push_back(blockArgs);
2532 }
2533 SmallVector<ValueRange> succBlockArgsRange =
2534 llvm::to_vector_of<ValueRange>(succBlockArgs);
2535 Location loc = translateLoc(inst->getDebugLoc());
2536 auto indBrOp = LLVM::IndirectBrOp::create(builder, loc, *basePtr,
2537 succBlockArgsRange, succBlocks);
2538
2539 mapNoResultOp(inst, indBrOp);
2540 return success();
2541 }
2542
2543 // Convert all instructions that have an mlirBuilder.
2544 if (succeeded(convertInstructionImpl(builder, inst, *this, iface)))
2545 return success();
2546
2547 return emitError(loc) << "unhandled instruction: " << diag(*inst);
2548}
2549
2550LogicalResult ModuleImport::processInstruction(llvm::Instruction *inst) {
2551 // FIXME: Support uses of SubtargetData.
2552 // FIXME: Add support for call / operand attributes.
2553 // FIXME: Add support for the cleanupret, catchret, catchswitch, callbr,
2554 // vaarg, catchpad, cleanuppad instructions.
2555
2556 // Convert LLVM intrinsics calls to MLIR intrinsics.
2557 if (auto *intrinsic = dyn_cast<llvm::IntrinsicInst>(inst))
2558 return convertIntrinsic(intrinsic);
2559
2560 // Process debug records attached to this instruction. Debug variable records
2561 // are stored for later processing after all SSA values are converted, while
2562 // debug label records can be converted immediately.
2563 if (inst->DebugMarker) {
2564 for (llvm::DbgRecord &dbgRecord : inst->DebugMarker->getDbgRecordRange()) {
2565 // Store debug variable records for later processing.
2566 if (auto *dbgVariableRecord =
2567 dyn_cast<llvm::DbgVariableRecord>(&dbgRecord)) {
2568 addDebugRecord(dbgVariableRecord);
2569 continue;
2570 }
2571 Location loc = translateLoc(dbgRecord.getDebugLoc());
2572 auto emitUnsupportedWarning = [&]() -> LogicalResult {
2573 if (!emitExpensiveWarnings)
2574 return success();
2575 std::string options;
2576 llvm::raw_string_ostream optionsStream(options);
2577 dbgRecord.print(optionsStream);
2578 emitWarning(loc) << "unhandled debug record " << optionsStream.str();
2579 return success();
2580 };
2581 // Convert the debug label records in-place.
2582 if (auto *dbgLabelRecord = dyn_cast<llvm::DbgLabelRecord>(&dbgRecord)) {
2583 DILabelAttr labelAttr =
2584 debugImporter->translate(dbgLabelRecord->getLabel());
2585 if (!labelAttr)
2586 return emitUnsupportedWarning();
2587 LLVM::DbgLabelOp::create(builder, loc, labelAttr);
2588 continue;
2589 }
2590 // Warn if an unsupported debug record is encountered.
2591 return emitUnsupportedWarning();
2592 }
2593 }
2594
2595 // Convert all remaining LLVM instructions to MLIR operations.
2596 return convertInstruction(inst);
2597}
2598
2599FlatSymbolRefAttr ModuleImport::getPersonalityAsAttr(llvm::Function *f) {
2600 if (!f->hasPersonalityFn())
2601 return nullptr;
2602
2603 llvm::Constant *pf = f->getPersonalityFn();
2604
2605 // If it directly has a name, we can use it.
2606 if (pf->hasName())
2607 return SymbolRefAttr::get(builder.getContext(), pf->getName());
2608
2609 // If it doesn't have a name, currently, only function pointers that are
2610 // bitcast to i8* are parsed.
2611 if (auto *ce = dyn_cast<llvm::ConstantExpr>(pf)) {
2612 if (ce->getOpcode() == llvm::Instruction::BitCast &&
2613 ce->getType() == llvm::PointerType::getUnqual(f->getContext())) {
2614 if (auto *func = dyn_cast<llvm::Function>(ce->getOperand(0)))
2615 return SymbolRefAttr::get(builder.getContext(), func->getName());
2616 }
2617 }
2618 return FlatSymbolRefAttr();
2619}
2620
2621static void processMemoryEffects(llvm::Function *func, LLVMFuncOp funcOp) {
2622 llvm::MemoryEffects memEffects = func->getMemoryEffects();
2623
2624 auto othermem = convertModRefInfoFromLLVM(
2625 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
2626 auto argMem = convertModRefInfoFromLLVM(
2627 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
2628 auto inaccessibleMem = convertModRefInfoFromLLVM(
2629 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
2630 auto errnoMem = convertModRefInfoFromLLVM(
2631 memEffects.getModRef(llvm::MemoryEffects::Location::ErrnoMem));
2632 auto targetMem0 = convertModRefInfoFromLLVM(
2633 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem0));
2634 auto targetMem1 = convertModRefInfoFromLLVM(
2635 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem1));
2636 auto memAttr =
2637 MemoryEffectsAttr::get(funcOp.getContext(), othermem, argMem,
2638 inaccessibleMem, errnoMem, targetMem0, targetMem1);
2639 // Only set the attr when it does not match the default value.
2640 if (memAttr.isReadWrite())
2641 return;
2642 funcOp.setMemoryEffectsAttr(memAttr);
2643}
2644
2645// List of LLVM IR attributes that map to an explicit attribute on the MLIR
2646// LLVMFuncOp.
2647static constexpr std::array kExplicitLLVMFuncOpAttributes{
2648 StringLiteral("aarch64_in_za"),
2649 StringLiteral("aarch64_inout_za"),
2650 StringLiteral("aarch64_new_za"),
2651 StringLiteral("aarch64_out_za"),
2652 StringLiteral("aarch64_preserves_za"),
2653 StringLiteral("aarch64_pstate_sm_body"),
2654 StringLiteral("aarch64_pstate_sm_compatible"),
2655 StringLiteral("aarch64_pstate_sm_enabled"),
2656 StringLiteral("alwaysinline"),
2657 StringLiteral("convergent"),
2658 StringLiteral("denormal-fp-math"),
2659 StringLiteral("denormal-fp-math-f32"),
2660 StringLiteral("fp-contract"),
2661 StringLiteral("frame-pointer"),
2662 StringLiteral("inlinehint"),
2663 StringLiteral("instrument-function-entry"),
2664 StringLiteral("instrument-function-exit"),
2665 StringLiteral("memory"),
2666 StringLiteral("no-infs-fp-math"),
2667 StringLiteral("no-nans-fp-math"),
2668 StringLiteral("no-signed-zeros-fp-math"),
2669 StringLiteral("noinline"),
2670 StringLiteral("nounwind"),
2671 StringLiteral("optnone"),
2672 StringLiteral("target-features"),
2673 StringLiteral("tune-cpu"),
2674 StringLiteral("uwtable"),
2675 StringLiteral("vscale_range"),
2676 StringLiteral("willreturn"),
2677};
2678
2679/// Converts LLVM attributes from `func` into MLIR attributes and adds them
2680/// to `funcOp` as passthrough attributes, skipping those listed in
2681/// `kExplicitLLVMFuncAttributes`.
2682static void processPassthroughAttrs(llvm::Function *func, LLVMFuncOp funcOp) {
2683 llvm::AttributeSet funcAttrs = func->getAttributes().getAttributes(
2684 llvm::AttributeList::AttrIndex::FunctionIndex);
2685 ArrayAttr passthroughAttr =
2686 convertLLVMAttributesToMLIR(funcOp.getLoc(), funcOp.getContext(),
2688 if (!passthroughAttr.empty())
2689 funcOp.setPassthroughAttr(passthroughAttr);
2690}
2691
2693 LLVMFuncOp funcOp) {
2694 processMemoryEffects(func, funcOp);
2696
2697 if (func->hasFnAttribute(llvm::Attribute::NoInline))
2698 funcOp.setNoInline(true);
2699 if (func->hasFnAttribute(llvm::Attribute::AlwaysInline))
2700 funcOp.setAlwaysInline(true);
2701 if (func->hasFnAttribute(llvm::Attribute::InlineHint))
2702 funcOp.setInlineHint(true);
2703 if (func->hasFnAttribute(llvm::Attribute::OptimizeNone))
2704 funcOp.setOptimizeNone(true);
2705 if (func->hasFnAttribute(llvm::Attribute::Convergent))
2706 funcOp.setConvergent(true);
2707 if (func->hasFnAttribute(llvm::Attribute::NoUnwind))
2708 funcOp.setNoUnwind(true);
2709 if (func->hasFnAttribute(llvm::Attribute::WillReturn))
2710 funcOp.setWillReturn(true);
2711
2712 if (func->hasFnAttribute("aarch64_pstate_sm_enabled"))
2713 funcOp.setArmStreaming(true);
2714 else if (func->hasFnAttribute("aarch64_pstate_sm_body"))
2715 funcOp.setArmLocallyStreaming(true);
2716 else if (func->hasFnAttribute("aarch64_pstate_sm_compatible"))
2717 funcOp.setArmStreamingCompatible(true);
2718
2719 if (func->hasFnAttribute("aarch64_new_za"))
2720 funcOp.setArmNewZa(true);
2721 else if (func->hasFnAttribute("aarch64_in_za"))
2722 funcOp.setArmInZa(true);
2723 else if (func->hasFnAttribute("aarch64_out_za"))
2724 funcOp.setArmOutZa(true);
2725 else if (func->hasFnAttribute("aarch64_inout_za"))
2726 funcOp.setArmInoutZa(true);
2727 else if (func->hasFnAttribute("aarch64_preserves_za"))
2728 funcOp.setArmPreservesZa(true);
2729
2730 llvm::Attribute attr = func->getFnAttribute(llvm::Attribute::VScaleRange);
2731 if (attr.isValid()) {
2732 MLIRContext *context = funcOp.getContext();
2733 auto intTy = IntegerType::get(context, 32);
2734 funcOp.setVscaleRangeAttr(LLVM::VScaleRangeAttr::get(
2735 context, IntegerAttr::get(intTy, attr.getVScaleRangeMin()),
2736 IntegerAttr::get(intTy, attr.getVScaleRangeMax().value_or(0))));
2737 }
2738
2739 // Process frame-pointer attribute.
2740 if (func->hasFnAttribute("frame-pointer")) {
2741 StringRef stringRefFramePointerKind =
2742 func->getFnAttribute("frame-pointer").getValueAsString();
2743 funcOp.setFramePointerAttr(LLVM::FramePointerKindAttr::get(
2744 funcOp.getContext(), LLVM::framePointerKind::symbolizeFramePointerKind(
2745 stringRefFramePointerKind)
2746 .value()));
2747 }
2748
2749 if (llvm::Attribute attr = func->getFnAttribute("target-cpu");
2750 attr.isStringAttribute())
2751 funcOp.setTargetCpuAttr(StringAttr::get(context, attr.getValueAsString()));
2752
2753 if (llvm::Attribute attr = func->getFnAttribute("tune-cpu");
2754 attr.isStringAttribute())
2755 funcOp.setTuneCpuAttr(StringAttr::get(context, attr.getValueAsString()));
2756
2757 if (llvm::Attribute attr = func->getFnAttribute("target-features");
2758 attr.isStringAttribute())
2759 funcOp.setTargetFeaturesAttr(
2760 LLVM::TargetFeaturesAttr::get(context, attr.getValueAsString()));
2761
2762 if (llvm::Attribute attr = func->getFnAttribute("reciprocal-estimates");
2763 attr.isStringAttribute())
2764 funcOp.setReciprocalEstimatesAttr(
2765 StringAttr::get(context, attr.getValueAsString()));
2766
2767 if (llvm::Attribute attr = func->getFnAttribute("prefer-vector-width");
2768 attr.isStringAttribute())
2769 funcOp.setPreferVectorWidth(attr.getValueAsString());
2770
2771 if (llvm::Attribute attr = func->getFnAttribute("no-infs-fp-math");
2772 attr.isStringAttribute())
2773 funcOp.setNoInfsFpMath(attr.getValueAsBool());
2774
2775 if (llvm::Attribute attr = func->getFnAttribute("no-nans-fp-math");
2776 attr.isStringAttribute())
2777 funcOp.setNoNansFpMath(attr.getValueAsBool());
2778
2779 if (llvm::Attribute attr = func->getFnAttribute("instrument-function-entry");
2780 attr.isStringAttribute())
2781 funcOp.setInstrumentFunctionEntry(
2782 StringAttr::get(context, attr.getValueAsString()));
2783
2784 if (llvm::Attribute attr = func->getFnAttribute("instrument-function-exit");
2785 attr.isStringAttribute())
2786 funcOp.setInstrumentFunctionExit(
2787 StringAttr::get(context, attr.getValueAsString()));
2788
2789 if (llvm::Attribute attr = func->getFnAttribute("no-signed-zeros-fp-math");
2790 attr.isStringAttribute())
2791 funcOp.setNoSignedZerosFpMath(attr.getValueAsBool());
2792
2793 if (llvm::Attribute attr = func->getFnAttribute("denormal-fp-math");
2794 attr.isStringAttribute())
2795 funcOp.setDenormalFpMathAttr(
2796 StringAttr::get(context, attr.getValueAsString()));
2797
2798 if (llvm::Attribute attr = func->getFnAttribute("denormal-fp-math-f32");
2799 attr.isStringAttribute())
2800 funcOp.setDenormalFpMathF32Attr(
2801 StringAttr::get(context, attr.getValueAsString()));
2802
2803 if (llvm::Attribute attr = func->getFnAttribute("fp-contract");
2804 attr.isStringAttribute())
2805 funcOp.setFpContractAttr(StringAttr::get(context, attr.getValueAsString()));
2806
2807 if (func->hasUWTable()) {
2808 ::llvm::UWTableKind uwtableKind = func->getUWTableKind();
2809 funcOp.setUwtableKindAttr(LLVM::UWTableKindAttr::get(
2810 funcOp.getContext(), convertUWTableKindFromLLVM(uwtableKind)));
2811 }
2812}
2813
2814DictionaryAttr
2815ModuleImport::convertArgOrResultAttrSet(llvm::AttributeSet llvmAttrSet) {
2816 SmallVector<NamedAttribute> paramAttrs;
2817 for (auto [llvmKind, mlirName] : getAttrKindToNameMapping()) {
2818 auto llvmAttr = llvmAttrSet.getAttribute(llvmKind);
2819 // Skip attributes that are not attached.
2820 if (!llvmAttr.isValid())
2821 continue;
2822
2823 // TODO: Import captures(none) as a nocapture unit attribute until the
2824 // LLVM dialect switches to the captures representation.
2825 if (llvmAttr.hasKindAsEnum() &&
2826 llvmAttr.getKindAsEnum() == llvm::Attribute::Captures) {
2827 if (llvm::capturesNothing(llvmAttr.getCaptureInfo()))
2828 paramAttrs.push_back(
2829 builder.getNamedAttr(mlirName, builder.getUnitAttr()));
2830 continue;
2831 }
2832
2833 Attribute mlirAttr;
2834 if (llvmAttr.isTypeAttribute())
2835 mlirAttr = TypeAttr::get(convertType(llvmAttr.getValueAsType()));
2836 else if (llvmAttr.isIntAttribute())
2837 mlirAttr = builder.getI64IntegerAttr(llvmAttr.getValueAsInt());
2838 else if (llvmAttr.isEnumAttribute())
2839 mlirAttr = builder.getUnitAttr();
2840 else if (llvmAttr.isConstantRangeAttribute()) {
2841 const llvm::ConstantRange &value = llvmAttr.getValueAsConstantRange();
2842 mlirAttr = builder.getAttr<LLVM::ConstantRangeAttr>(value.getLower(),
2843 value.getUpper());
2844 } else {
2845 llvm_unreachable("unexpected parameter attribute kind");
2846 }
2847 paramAttrs.push_back(builder.getNamedAttr(mlirName, mlirAttr));
2848 }
2849
2850 return builder.getDictionaryAttr(paramAttrs);
2851}
2852
2853void ModuleImport::convertArgAndResultAttrs(llvm::Function *func,
2854 LLVMFuncOp funcOp) {
2855 auto llvmAttrs = func->getAttributes();
2856 for (size_t i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
2857 llvm::AttributeSet llvmArgAttrs = llvmAttrs.getParamAttrs(i);
2858 funcOp.setArgAttrs(i, convertArgOrResultAttrSet(llvmArgAttrs));
2859 }
2860 // Convert the result attributes and attach them wrapped in an ArrayAttribute
2861 // to the funcOp.
2862 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
2863 if (!llvmResAttr.hasAttributes())
2864 return;
2865 funcOp.setResAttrsAttr(
2866 builder.getArrayAttr({convertArgOrResultAttrSet(llvmResAttr)}));
2867}
2868
2870 llvm::CallBase *call, ArgAndResultAttrsOpInterface attrsOp,
2871 ArrayRef<unsigned> immArgPositions) {
2872 // Compute the set of immediate argument positions.
2873 llvm::SmallDenseSet<unsigned> immArgPositionsSet(immArgPositions.begin(),
2874 immArgPositions.end());
2875 // Convert the argument attributes and filter out immediate arguments.
2876 llvm::AttributeList llvmAttrs = call->getAttributes();
2877 SmallVector<llvm::AttributeSet> llvmArgAttrsSet;
2878 bool anyArgAttrs = false;
2879 for (size_t i = 0, e = call->arg_size(); i < e; ++i) {
2880 // Skip immediate arguments.
2881 if (immArgPositionsSet.contains(i))
2882 continue;
2883 llvmArgAttrsSet.emplace_back(llvmAttrs.getParamAttrs(i));
2884 if (llvmArgAttrsSet.back().hasAttributes())
2885 anyArgAttrs = true;
2886 }
2887 auto getArrayAttr = [&](ArrayRef<DictionaryAttr> dictAttrs) {
2889 for (auto &dict : dictAttrs)
2890 attrs.push_back(dict ? dict : builder.getDictionaryAttr({}));
2891 return builder.getArrayAttr(attrs);
2892 };
2893 if (anyArgAttrs) {
2895 for (auto &llvmArgAttrs : llvmArgAttrsSet)
2896 argAttrs.emplace_back(convertArgOrResultAttrSet(llvmArgAttrs));
2897 attrsOp.setArgAttrsAttr(getArrayAttr(argAttrs));
2898 }
2899
2900 // Convert the result attributes.
2901 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
2902 if (!llvmResAttr.hasAttributes())
2903 return;
2904 DictionaryAttr resAttrs = convertArgOrResultAttrSet(llvmResAttr);
2905 attrsOp.setResAttrsAttr(getArrayAttr({resAttrs}));
2906}
2907
2908template <typename Op>
2909static LogicalResult convertCallBaseAttributes(llvm::CallBase *inst, Op op) {
2910 op.setCConv(convertCConvFromLLVM(inst->getCallingConv()));
2911 return success();
2912}
2913
2914LogicalResult ModuleImport::convertInvokeAttributes(llvm::InvokeInst *inst,
2915 InvokeOp op) {
2916 return convertCallBaseAttributes(inst, op);
2917}
2918
2919LogicalResult ModuleImport::convertCallAttributes(llvm::CallInst *inst,
2920 CallOp op) {
2921 setFastmathFlagsAttr(inst, op.getOperation());
2922 // Query the attributes directly instead of using `inst->getFnAttr(Kind)`, the
2923 // latter does additional lookup to the parent and inherits, changing the
2924 // semantics too early.
2925 llvm::AttributeList callAttrs = inst->getAttributes();
2926
2927 op.setTailCallKind(convertTailCallKindFromLLVM(inst->getTailCallKind()));
2928 op.setConvergent(callAttrs.getFnAttr(llvm::Attribute::Convergent).isValid());
2929 op.setNoUnwind(callAttrs.getFnAttr(llvm::Attribute::NoUnwind).isValid());
2930 op.setWillReturn(callAttrs.getFnAttr(llvm::Attribute::WillReturn).isValid());
2931 op.setNoInline(callAttrs.getFnAttr(llvm::Attribute::NoInline).isValid());
2932 op.setAlwaysInline(
2933 callAttrs.getFnAttr(llvm::Attribute::AlwaysInline).isValid());
2934 op.setInlineHint(callAttrs.getFnAttr(llvm::Attribute::InlineHint).isValid());
2935
2936 llvm::MemoryEffects memEffects = inst->getMemoryEffects();
2937 ModRefInfo othermem = convertModRefInfoFromLLVM(
2938 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
2939 ModRefInfo argMem = convertModRefInfoFromLLVM(
2940 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
2941 ModRefInfo inaccessibleMem = convertModRefInfoFromLLVM(
2942 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
2943 ModRefInfo errnoMem = convertModRefInfoFromLLVM(
2944 memEffects.getModRef(llvm::MemoryEffects::Location::ErrnoMem));
2945 ModRefInfo targetMem0 = convertModRefInfoFromLLVM(
2946 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem0));
2947 ModRefInfo targetMem1 = convertModRefInfoFromLLVM(
2948 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem1));
2949 auto memAttr =
2950 MemoryEffectsAttr::get(op.getContext(), othermem, argMem, inaccessibleMem,
2951 errnoMem, targetMem0, targetMem1);
2952 // Only set the attribute when it does not match the default value.
2953 if (!memAttr.isReadWrite())
2954 op.setMemoryEffectsAttr(memAttr);
2955
2956 return convertCallBaseAttributes(inst, op);
2957}
2958
2959LogicalResult ModuleImport::processFunction(llvm::Function *func) {
2960 clearRegionState();
2961
2962 auto functionType =
2963 dyn_cast<LLVMFunctionType>(convertType(func->getFunctionType()));
2964 if (func->isIntrinsic() &&
2965 iface.isConvertibleIntrinsic(func->getIntrinsicID()))
2966 return success();
2967
2968 bool dsoLocal = func->isDSOLocal();
2969 CConv cconv = convertCConvFromLLVM(func->getCallingConv());
2970
2971 // Insert the function at the end of the module.
2972 OpBuilder::InsertionGuard guard(builder);
2973 builder.setInsertionPointToEnd(mlirModule.getBody());
2974
2975 Location loc = debugImporter->translateFuncLocation(func);
2976 LLVMFuncOp funcOp = LLVMFuncOp::create(
2977 builder, loc, func->getName(), functionType,
2978 convertLinkageFromLLVM(func->getLinkage()), dsoLocal, cconv);
2979
2981
2982 if (FlatSymbolRefAttr personality = getPersonalityAsAttr(func))
2983 funcOp.setPersonalityAttr(personality);
2984 else if (func->hasPersonalityFn())
2985 emitWarning(funcOp.getLoc(), "could not deduce personality, skipping it");
2986
2987 if (func->hasGC())
2988 funcOp.setGarbageCollector(StringRef(func->getGC()));
2989
2990 if (func->hasAtLeastLocalUnnamedAddr())
2991 funcOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(func->getUnnamedAddr()));
2992
2993 if (func->hasSection())
2994 funcOp.setSection(StringRef(func->getSection()));
2995
2996 funcOp.setVisibility_(convertVisibilityFromLLVM(func->getVisibility()));
2997
2998 if (func->hasComdat())
2999 funcOp.setComdatAttr(comdatMapping.lookup(func->getComdat()));
3000
3001 if (llvm::MaybeAlign maybeAlign = func->getAlign())
3002 funcOp.setAlignment(maybeAlign->value());
3003
3004 // Handle Function attributes.
3006
3007 // Convert non-debug metadata by using the dialect interface.
3009 func->getAllMetadata(allMetadata);
3010 for (auto &[kind, node] : allMetadata) {
3011 if (!iface.isConvertibleMetadata(kind))
3012 continue;
3013 if (failed(iface.setMetadataAttrs(builder, kind, node, funcOp, *this))) {
3014 emitWarning(funcOp.getLoc())
3015 << "unhandled function metadata: " << diagMD(node, llvmModule.get())
3016 << " on " << diag(*func);
3017 }
3018 }
3019
3020 if (func->isDeclaration())
3021 return success();
3022
3023 // Collect the set of basic blocks reachable from the function's entry block.
3024 // This step is crucial as LLVM IR can contain unreachable blocks that
3025 // self-dominate. As a result, an operation might utilize a variable it
3026 // defines, which the import does not support. Given that MLIR lacks block
3027 // label support, we can safely remove unreachable blocks, as there are no
3028 // indirect branch instructions that could potentially target these blocks.
3029 llvm::df_iterator_default_set<llvm::BasicBlock *> reachable;
3030 for (llvm::BasicBlock *basicBlock : llvm::depth_first_ext(func, reachable))
3031 (void)basicBlock;
3032
3033 // Eagerly create all reachable blocks.
3034 SmallVector<llvm::BasicBlock *> reachableBasicBlocks;
3035 for (llvm::BasicBlock &basicBlock : *func) {
3036 // Skip unreachable blocks.
3037 if (!reachable.contains(&basicBlock)) {
3038 if (basicBlock.hasAddressTaken())
3039 return emitError(funcOp.getLoc())
3040 << "unreachable block '" << basicBlock.getName()
3041 << "' with address taken";
3042 continue;
3043 }
3044 Region &body = funcOp.getBody();
3045 Block *block = builder.createBlock(&body, body.end());
3046 mapBlock(&basicBlock, block);
3047 reachableBasicBlocks.push_back(&basicBlock);
3048 }
3049
3050 // Add function arguments to the entry block.
3051 for (const auto &it : llvm::enumerate(func->args())) {
3052 BlockArgument blockArg = funcOp.getFunctionBody().addArgument(
3053 functionType.getParamType(it.index()), funcOp.getLoc());
3054 mapValue(&it.value(), blockArg);
3055 }
3056
3057 // Process the blocks in topological order. The ordered traversal ensures
3058 // operands defined in a dominating block have a valid mapping to an MLIR
3059 // value once a block is translated.
3061 getTopologicallySortedBlocks(reachableBasicBlocks);
3062 setConstantInsertionPointToStart(lookupBlock(blocks.front()));
3063 for (llvm::BasicBlock *basicBlock : blocks)
3064 if (failed(processBasicBlock(basicBlock, lookupBlock(basicBlock))))
3065 return failure();
3066
3067 // Process the debug intrinsics that require a delayed conversion after
3068 // everything else was converted.
3069 if (failed(processDebugIntrinsics()))
3070 return failure();
3071
3072 // Process the debug records that require a delayed conversion after
3073 // everything else was converted.
3074 if (failed(processDebugRecords()))
3075 return failure();
3076
3077 return success();
3078}
3079
3080/// Checks if `dbgIntr` is a kill location that holds metadata instead of an SSA
3081/// value.
3082static bool isMetadataKillLocation(llvm::DbgVariableIntrinsic *dbgIntr) {
3083 if (!dbgIntr->isKillLocation())
3084 return false;
3085 llvm::Value *value = dbgIntr->getArgOperand(0);
3086 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
3087 if (!nodeAsVal)
3088 return false;
3089 return !isa<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
3090}
3091
3092/// Ensure that the debug intrinsic is inserted right after the operand
3093/// definition. Otherwise, the operand might not necessarily dominate the
3094/// intrinsic. If the defining operation is a terminator, insert the intrinsic
3095/// into a dominated block.
3097 mlir::OpBuilder &builder, DominanceInfo &domInfo, Value argOperand) {
3098 if (Operation *op = argOperand.getDefiningOp();
3099 op && op->hasTrait<OpTrait::IsTerminator>()) {
3100 // Find a dominated block that can hold the debug intrinsic.
3101 auto dominatedBlocks = domInfo.getNode(op->getBlock())->children();
3102 // If no block is dominated by the terminator, this intrinisc cannot be
3103 // converted.
3104 if (dominatedBlocks.empty())
3105 return failure();
3106 // Set insertion point before the terminator, to avoid inserting something
3107 // before landingpads.
3108 Block *dominatedBlock = (*dominatedBlocks.begin())->getBlock();
3109 builder.setInsertionPoint(dominatedBlock->getTerminator());
3110 } else {
3111 Value insertPt = argOperand;
3112 if (auto blockArg = dyn_cast<BlockArgument>(argOperand)) {
3113 // The value might be coming from a phi node and is now a block argument,
3114 // which means the insertion point is set to the start of the block. If
3115 // this block is a target destination of an invoke, the insertion point
3116 // must happen after the landing pad operation.
3117 Block *insertionBlock = argOperand.getParentBlock();
3118 if (!insertionBlock->empty() &&
3119 isa<LandingpadOp>(insertionBlock->front()))
3120 insertPt = cast<LandingpadOp>(insertionBlock->front()).getRes();
3121 }
3122
3123 builder.setInsertionPointAfterValue(insertPt);
3124 }
3125 return success();
3126}
3127
3128std::tuple<DILocalVariableAttr, DIExpressionAttr, Value>
3129ModuleImport::processDebugOpArgumentsAndInsertionPt(
3130 Location loc,
3131 llvm::function_ref<FailureOr<Value>()> convertArgOperandToValue,
3132 llvm::Value *address,
3133 llvm::PointerUnion<llvm::Value *, llvm::DILocalVariable *> variable,
3134 llvm::DIExpression *expression, DominanceInfo &domInfo) {
3135 // Drop debug intrinsics if the associated debug information cannot be
3136 // translated due to an unsupported construct.
3137 DILocalVariableAttr localVarAttr = matchLocalVariableAttr(variable);
3138 if (!localVarAttr)
3139 return {};
3140 FailureOr<Value> argOperand = convertArgOperandToValue();
3141 if (failed(argOperand)) {
3142 emitError(loc) << "failed to convert a debug operand: " << diag(*address);
3143 return {};
3144 }
3145
3146 if (setDebugIntrinsicBuilderInsertionPoint(builder, domInfo, *argOperand)
3147 .failed())
3148 return {};
3149
3150 return {localVarAttr, debugImporter->translateExpression(expression),
3151 *argOperand};
3152}
3153
3154LogicalResult
3155ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr,
3156 DominanceInfo &domInfo) {
3157 Location loc = translateLoc(dbgIntr->getDebugLoc());
3158 auto emitUnsupportedWarning = [&]() {
3159 if (emitExpensiveWarnings)
3160 emitWarning(loc) << "dropped intrinsic: " << diag(*dbgIntr);
3161 return success();
3162 };
3163
3164 OpBuilder::InsertionGuard guard(builder);
3165 auto convertArgOperandToValue = [&]() {
3166 return convertMetadataValue(dbgIntr->getArgOperand(0));
3167 };
3168
3169 // Drop debug intrinsics with an argument list.
3170 // TODO: Support this case.
3171 if (dbgIntr->hasArgList())
3172 return emitUnsupportedWarning();
3173
3174 // Drop debug intrinsics with kill locations that have metadata nodes as
3175 // location operand, which cannot be converted to poison as the type cannot be
3176 // reconstructed.
3177 // TODO: Support this case.
3178 if (isMetadataKillLocation(dbgIntr))
3179 return emitUnsupportedWarning();
3180
3181 auto [localVariableAttr, locationExprAttr, locVal] =
3182 processDebugOpArgumentsAndInsertionPt(
3183 loc, convertArgOperandToValue, dbgIntr->getArgOperand(0),
3184 dbgIntr->getArgOperand(1), dbgIntr->getExpression(), domInfo);
3185
3186 if (!localVariableAttr)
3187 return emitUnsupportedWarning();
3188
3189 if (!locVal) // Expected if localVariableAttr is present.
3190 return failure();
3191
3192 Operation *op = nullptr;
3193 if (isa<llvm::DbgDeclareInst>(dbgIntr))
3194 op = LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,
3195 locationExprAttr);
3196 else if (isa<llvm::DbgValueInst>(dbgIntr))
3197 op = LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,
3198 locationExprAttr);
3199 else
3200 return emitUnsupportedWarning();
3201
3202 mapNoResultOp(dbgIntr, op);
3203 setNonDebugMetadataAttrs(dbgIntr, op);
3204 return success();
3205}
3206
3207LogicalResult
3208ModuleImport::processDebugRecord(llvm::DbgVariableRecord &dbgRecord,
3209 DominanceInfo &domInfo) {
3210 OpBuilder::InsertionGuard guard(builder);
3211 Location loc = translateLoc(dbgRecord.getDebugLoc());
3212 auto emitUnsupportedWarning = [&]() -> LogicalResult {
3213 if (!emitExpensiveWarnings)
3214 return success();
3215 std::string options;
3216 llvm::raw_string_ostream optionsStream(options);
3217 dbgRecord.print(optionsStream);
3218 emitWarning(loc) << "unhandled debug variable record "
3219 << optionsStream.str();
3220 return success();
3221 };
3222
3223 // Drop debug records with an argument list.
3224 // TODO: Support this case.
3225 if (dbgRecord.hasArgList())
3226 return emitUnsupportedWarning();
3227
3228 // Drop all other debug records with a address operand that cannot be
3229 // converted to an SSA value such as an empty metadata node.
3230 // TODO: Support this case.
3231 if (!dbgRecord.getAddress())
3232 return emitUnsupportedWarning();
3233
3234 auto convertArgOperandToValue = [&]() -> FailureOr<Value> {
3235 llvm::Value *value = dbgRecord.getAddress();
3236
3237 // Return the mapped value if it has been converted before.
3238 auto it = valueMapping.find(value);
3239 if (it != valueMapping.end())
3240 return it->getSecond();
3241
3242 // Convert constants such as immediate values that have no mapping yet.
3243 if (auto *constant = dyn_cast<llvm::Constant>(value))
3244 return convertConstantExpr(constant);
3245 return failure();
3246 };
3247
3248 auto [localVariableAttr, locationExprAttr, locVal] =
3249 processDebugOpArgumentsAndInsertionPt(
3250 loc, convertArgOperandToValue, dbgRecord.getAddress(),
3251 dbgRecord.getVariable(), dbgRecord.getExpression(), domInfo);
3252
3253 if (!localVariableAttr)
3254 return emitUnsupportedWarning();
3255
3256 if (!locVal) // Expected if localVariableAttr is present.
3257 return failure();
3258
3259 if (dbgRecord.isDbgDeclare())
3260 LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,
3261 locationExprAttr);
3262 else if (dbgRecord.isDbgValue())
3263 LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,
3264 locationExprAttr);
3265 else // isDbgAssign
3266 return emitUnsupportedWarning();
3267
3268 return success();
3269}
3270
3271LogicalResult ModuleImport::processDebugIntrinsics() {
3272 DominanceInfo domInfo;
3273 for (llvm::Instruction *inst : debugIntrinsics) {
3274 auto *intrCall = cast<llvm::DbgVariableIntrinsic>(inst);
3275 if (failed(processDebugIntrinsic(intrCall, domInfo)))
3276 return failure();
3277 }
3278 return success();
3279}
3280
3281LogicalResult ModuleImport::processDebugRecords() {
3282 DominanceInfo domInfo;
3283 for (llvm::DbgVariableRecord *dbgRecord : dbgRecords)
3284 if (failed(processDebugRecord(*dbgRecord, domInfo)))
3285 return failure();
3286 dbgRecords.clear();
3287 return success();
3288}
3289
3290LogicalResult ModuleImport::processBasicBlock(llvm::BasicBlock *bb,
3291 Block *block) {
3292 builder.setInsertionPointToStart(block);
3293 for (llvm::Instruction &inst : *bb) {
3294 if (failed(processInstruction(&inst)))
3295 return failure();
3296
3297 // Skip additional processing when the instructions is a debug intrinsics
3298 // that was not yet converted.
3299 if (debugIntrinsics.contains(&inst))
3300 continue;
3301
3302 // Set the non-debug metadata attributes on the imported operation and emit
3303 // a warning if an instruction other than a phi instruction is dropped
3304 // during the import.
3305 if (Operation *op = lookupOperation(&inst)) {
3306 setNonDebugMetadataAttrs(&inst, op);
3307 } else if (inst.getOpcode() != llvm::Instruction::PHI) {
3308 if (emitExpensiveWarnings) {
3309 Location loc = debugImporter->translateLoc(inst.getDebugLoc());
3310 emitWarning(loc) << "dropped instruction: " << diag(inst);
3311 }
3312 }
3313 }
3314
3315 if (bb->hasAddressTaken()) {
3316 OpBuilder::InsertionGuard guard(builder);
3317 builder.setInsertionPointToStart(block);
3318 BlockTagOp::create(builder, block->getParentOp()->getLoc(),
3319 BlockTagAttr::get(context, bb->getNumber()));
3320 }
3321 return success();
3322}
3323
3324FailureOr<SmallVector<AccessGroupAttr>>
3325ModuleImport::lookupAccessGroupAttrs(const llvm::MDNode *node) const {
3326 return loopAnnotationImporter->lookupAccessGroupAttrs(node);
3327}
3328
3329LoopAnnotationAttr
3331 Location loc) const {
3332 return loopAnnotationImporter->translateLoopAnnotation(node, loc);
3333}
3334
3335FailureOr<DereferenceableAttr>
3337 unsigned kindID) {
3338 Location loc = mlirModule.getLoc();
3339
3340 // The only operand should be a constant integer representing the number of
3341 // dereferenceable bytes.
3342 if (node->getNumOperands() != 1)
3343 return emitError(loc) << "dereferenceable metadata must have one operand: "
3344 << diagMD(node, llvmModule.get());
3345
3346 auto *numBytesMD = dyn_cast<llvm::ConstantAsMetadata>(node->getOperand(0));
3347 auto *numBytesCst = dyn_cast<llvm::ConstantInt>(numBytesMD->getValue());
3348 if (!numBytesCst || !numBytesCst->getValue().isNonNegative())
3349 return emitError(loc) << "dereferenceable metadata operand must be a "
3350 "non-negative constant integer: "
3351 << diagMD(node, llvmModule.get());
3352
3353 bool mayBeNull = kindID == llvm::LLVMContext::MD_dereferenceable_or_null;
3354 auto derefAttr = builder.getAttr<DereferenceableAttr>(
3355 numBytesCst->getZExtValue(), mayBeNull);
3356
3357 return derefAttr;
3358}
3359
3361 std::unique_ptr<llvm::Module> llvmModule, MLIRContext *context,
3362 bool emitExpensiveWarnings, bool dropDICompositeTypeElements,
3363 bool loadAllDialects, bool preferUnregisteredIntrinsics,
3364 bool importStructsAsLiterals) {
3365 // Preload all registered dialects to allow the import to iterate the
3366 // registered LLVMImportDialectInterface implementations and query the
3367 // supported LLVM IR constructs before starting the translation. Assumes the
3368 // LLVM and DLTI dialects that convert the core LLVM IR constructs have been
3369 // registered before.
3370 assert(llvm::is_contained(context->getAvailableDialects(),
3371 LLVMDialect::getDialectNamespace()));
3372 assert(llvm::is_contained(context->getAvailableDialects(),
3373 DLTIDialect::getDialectNamespace()));
3374 if (loadAllDialects)
3375 context->loadAllAvailableDialects();
3376 OwningOpRef<ModuleOp> module(ModuleOp::create(FileLineColLoc::get(
3377 StringAttr::get(context, llvmModule->getSourceFileName()), /*line=*/0,
3378 /*column=*/0)));
3379
3380 ModuleImport moduleImport(module.get(), std::move(llvmModule),
3381 emitExpensiveWarnings, dropDICompositeTypeElements,
3382 preferUnregisteredIntrinsics,
3383 importStructsAsLiterals);
3384 if (failed(moduleImport.initializeImportInterface()))
3385 return {};
3386 if (failed(moduleImport.convertDataLayout()))
3387 return {};
3388 if (failed(moduleImport.convertComdats()))
3389 return {};
3390 if (failed(moduleImport.convertMetadata()))
3391 return {};
3392 if (failed(moduleImport.convertGlobals()))
3393 return {};
3394 if (failed(moduleImport.convertFunctions()))
3395 return {};
3396 if (failed(moduleImport.convertAliases()))
3397 return {};
3398 if (failed(moduleImport.convertIFuncs()))
3399 return {};
3400 moduleImport.convertTargetTriple();
3401 moduleImport.convertModuleLevelAsm();
3402 return module;
3403}
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:561
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.