MLIR 23.0.0git
ModuleImport.cpp
Go to the documentation of this file.
1//===- ModuleImport.cpp - LLVM to MLIR conversion ---------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the import of an LLVM IR module into an LLVM dialect
10// module.
11//
12//===----------------------------------------------------------------------===//
13
17
18#include "AttrKindDetail.h"
19#include "DebugImporter.h"
21
24#include "mlir/IR/Builders.h"
25#include "mlir/IR/Matchers.h"
29
30#include "llvm/ADT/DepthFirstIterator.h"
31#include "llvm/ADT/PostOrderIterator.h"
32#include "llvm/ADT/ScopeExit.h"
33#include "llvm/ADT/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 if (constScalar->getType()->isVectorTy())
1225 return {};
1226
1227 // Convert scalar integers.
1228 if (auto *constInt = dyn_cast<llvm::ConstantInt>(constScalar)) {
1229 return builder.getIntegerAttr(
1230 IntegerType::get(context, constInt->getBitWidth()),
1231 constInt->getValue());
1232 }
1233
1234 // Convert scalar floats.
1235 if (auto *constFloat = dyn_cast<llvm::ConstantFP>(constScalar)) {
1236 llvm::Type *type = constFloat->getType();
1237 FloatType floatType =
1238 type->isBFloatTy()
1239 ? BFloat16Type::get(context)
1240 : LLVM::detail::getFloatType(context, type->getScalarSizeInBits());
1241 if (!floatType) {
1242 emitError(UnknownLoc::get(builder.getContext()))
1243 << "unexpected floating-point type";
1244 return {};
1245 }
1246 return builder.getFloatAttr(floatType, constFloat->getValueAPF());
1247 }
1248 return {};
1249}
1250
1251/// Returns an integer or float attribute array for the provided constant
1252/// sequence `constSequence` or nullptr if the conversion fails.
1253static SmallVector<Attribute>
1255 llvm::ConstantDataSequential *constSequence) {
1256 SmallVector<Attribute> elementAttrs;
1257 elementAttrs.reserve(constSequence->getNumElements());
1258 for (auto idx : llvm::seq<int64_t>(0, constSequence->getNumElements())) {
1259 llvm::Constant *constElement = constSequence->getElementAsConstant(idx);
1260 elementAttrs.push_back(getScalarConstantAsAttr(builder, constElement));
1261 }
1262 return elementAttrs;
1263}
1264
1265Attribute ModuleImport::getConstantAsAttr(llvm::Constant *constant) {
1266 // Convert scalar constants.
1267 if (Attribute scalarAttr = getScalarConstantAsAttr(builder, constant))
1268 return scalarAttr;
1269
1270 // Returns the static shape of the provided type if possible.
1271 auto getConstantShape = [&](llvm::Type *type) {
1272 return llvm::dyn_cast_if_present<ShapedType>(
1273 getBuiltinTypeForAttr(convertType(type)));
1274 };
1275
1276 // Convert constant vector splat values.
1277 if (isa<llvm::ConstantInt, llvm::ConstantFP>(constant)) {
1278 assert(constant->getType()->isVectorTy() && "expected a vector splat");
1279 auto shape = getConstantShape(constant->getType());
1280 if (!shape)
1281 return {};
1282 Attribute splatAttr =
1283 getScalarConstantAsAttr(builder, constant->getSplatValue());
1284 return SplatElementsAttr::get(shape, splatAttr);
1285 }
1286
1287 // Convert one-dimensional constant arrays or vectors that store 1/2/4/8-byte
1288 // integer or half/bfloat/float/double values.
1289 if (auto *constArray = dyn_cast<llvm::ConstantDataSequential>(constant)) {
1290 if (constArray->isString())
1291 return builder.getStringAttr(constArray->getAsString());
1292 auto shape = getConstantShape(constArray->getType());
1293 if (!shape)
1294 return {};
1295 // Convert splat constants to splat elements attributes.
1296 auto *constVector = dyn_cast<llvm::ConstantDataVector>(constant);
1297 if (constVector && constVector->isSplat()) {
1298 // A vector is guaranteed to have at least size one.
1299 Attribute splatAttr = getScalarConstantAsAttr(
1300 builder, constVector->getElementAsConstant(0));
1301 return SplatElementsAttr::get(shape, splatAttr);
1302 }
1303 // Convert non-splat constants to dense elements attributes.
1304 SmallVector<Attribute> elementAttrs =
1305 getSequenceConstantAsAttrs(builder, constArray);
1306 return DenseElementsAttr::get(shape, elementAttrs);
1307 }
1308
1309 // Convert multi-dimensional constant aggregates that store all kinds of
1310 // integer and floating-point types.
1311 if (auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(constant)) {
1312 auto shape = getConstantShape(constAggregate->getType());
1313 if (!shape)
1314 return {};
1315 // Collect the aggregate elements in depths first order.
1316 SmallVector<Attribute> elementAttrs;
1317 SmallVector<llvm::Constant *> workList = {constAggregate};
1318 while (!workList.empty()) {
1319 llvm::Constant *current = workList.pop_back_val();
1320 // Append any nested aggregates in reverse order to ensure the head
1321 // element of the nested aggregates is at the back of the work list.
1322 if (auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(current)) {
1323 for (auto idx :
1324 reverse(llvm::seq<int64_t>(0, constAggregate->getNumOperands())))
1325 workList.push_back(constAggregate->getAggregateElement(idx));
1326 continue;
1327 }
1328 // Append the elements of nested constant arrays or vectors that store
1329 // 1/2/4/8-byte integer or half/bfloat/float/double values.
1330 if (auto *constArray = dyn_cast<llvm::ConstantDataSequential>(current)) {
1331 SmallVector<Attribute> attrs =
1332 getSequenceConstantAsAttrs(builder, constArray);
1333 elementAttrs.append(attrs.begin(), attrs.end());
1334 continue;
1335 }
1336 // Append nested scalar constants that store all kinds of integer and
1337 // floating-point types.
1338 if (Attribute scalarAttr = getScalarConstantAsAttr(builder, current)) {
1339 elementAttrs.push_back(scalarAttr);
1340 continue;
1341 }
1342 // Bail if the aggregate contains a unsupported constant type such as a
1343 // constant expression.
1344 return {};
1345 }
1346 return DenseElementsAttr::get(shape, elementAttrs);
1347 }
1348
1349 // Convert zero aggregates.
1350 if (auto *constZero = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1351 auto shape = llvm::dyn_cast_if_present<ShapedType>(
1352 getBuiltinTypeForAttr(convertType(constZero->getType())));
1353 if (!shape)
1354 return {};
1355 // Convert zero aggregates with a static shape to splat elements attributes.
1356 Attribute splatAttr = builder.getZeroAttr(shape.getElementType());
1357 assert(splatAttr && "expected non-null zero attribute for scalar types");
1358 return SplatElementsAttr::get(shape, splatAttr);
1359 }
1360 return {};
1361}
1362
1363FlatSymbolRefAttr
1364ModuleImport::getOrCreateNamelessSymbolName(llvm::GlobalVariable *globalVar) {
1365 assert(globalVar->getName().empty() &&
1366 "expected to work with a nameless global");
1367 auto [it, success] = namelessGlobals.try_emplace(globalVar);
1368 if (!success)
1369 return it->second;
1370
1371 // Make sure the symbol name does not clash with an existing symbol.
1372 SmallString<128> globalName = SymbolTable::generateSymbolName<128>(
1374 [this](StringRef newName) { return llvmModule->getNamedValue(newName); },
1375 namelessGlobalId);
1376 auto symbolRef = FlatSymbolRefAttr::get(context, globalName);
1377 it->getSecond() = symbolRef;
1378 return symbolRef;
1379}
1380
1381OpBuilder::InsertionGuard ModuleImport::setGlobalInsertionPoint() {
1382 OpBuilder::InsertionGuard guard(builder);
1383 if (globalInsertionOp)
1384 builder.setInsertionPointAfter(globalInsertionOp);
1385 else
1386 builder.setInsertionPointToStart(mlirModule.getBody());
1387 return guard;
1388}
1389
1390LogicalResult ModuleImport::convertAlias(llvm::GlobalAlias *alias) {
1391 // Insert the alias after the last one or at the start of the module.
1392 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1393
1394 Type type = convertType(alias->getValueType());
1395 AliasOp aliasOp = AliasOp::create(builder, mlirModule.getLoc(), type,
1396 convertLinkageFromLLVM(alias->getLinkage()),
1397 alias->getName(),
1398 /*dsoLocal=*/alias->isDSOLocal(),
1399 /*thread_local=*/alias->isThreadLocal(),
1400 /*attrs=*/ArrayRef<NamedAttribute>());
1401 globalInsertionOp = aliasOp;
1402
1403 clearRegionState();
1404 Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
1405 setConstantInsertionPointToStart(block);
1406 FailureOr<Value> initializer = convertConstantExpr(alias->getAliasee());
1407 if (failed(initializer))
1408 return failure();
1409 ReturnOp::create(builder, aliasOp.getLoc(), *initializer);
1410
1411 if (alias->hasAtLeastLocalUnnamedAddr())
1412 aliasOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(alias->getUnnamedAddr()));
1413 aliasOp.setVisibility_(convertVisibilityFromLLVM(alias->getVisibility()));
1414
1415 return success();
1416}
1417
1418LogicalResult ModuleImport::convertIFunc(llvm::GlobalIFunc *ifunc) {
1419 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1420
1421 Type type = convertType(ifunc->getValueType());
1422 llvm::Constant *resolver = ifunc->getResolver();
1423 Type resolverType = convertType(resolver->getType());
1424 IFuncOp::create(builder, mlirModule.getLoc(), ifunc->getName(), type,
1425 resolver->getName(), resolverType,
1426 convertLinkageFromLLVM(ifunc->getLinkage()),
1427 ifunc->isDSOLocal(), ifunc->getAddressSpace(),
1428 convertUnnamedAddrFromLLVM(ifunc->getUnnamedAddr()),
1429 convertVisibilityFromLLVM(ifunc->getVisibility()));
1430 return success();
1431}
1432
1433/// Converts LLVM string, integer, and enum attributes into MLIR attributes,
1434/// skipping those in `attributesToSkip` and emitting a warning at `loc` for
1435/// any other unsupported attributes.
1437 Location loc, MLIRContext *context, llvm::AttributeSet attributes,
1438 ArrayRef<StringLiteral> attributesToSkip = {},
1439 ArrayRef<StringLiteral> attributePrefixesToSkip = {}) {
1440 SmallVector<Attribute> mlirAttributes;
1441 for (llvm::Attribute attr : attributes) {
1442 StringRef attrName;
1443 if (attr.isStringAttribute())
1444 attrName = attr.getKindAsString();
1445 else
1446 attrName = llvm::Attribute::getNameFromAttrKind(attr.getKindAsEnum());
1447 if (llvm::is_contained(attributesToSkip, attrName))
1448 continue;
1449
1450 auto attrNameStartsWith = [attrName](StringLiteral sl) {
1451 return attrName.starts_with(sl);
1452 };
1453 if (attributePrefixesToSkip.end() !=
1454 llvm::find_if(attributePrefixesToSkip, attrNameStartsWith))
1455 continue;
1456
1457 auto keyAttr = StringAttr::get(context, attrName);
1458 if (attr.isStringAttribute()) {
1459 StringRef val = attr.getValueAsString();
1460 if (val.empty()) {
1461 // For string attributes without values, add only the attribute name.
1462 mlirAttributes.push_back(keyAttr);
1463 continue;
1464 }
1465 // For string attributes with a value, create a [name, value] pair.
1466 mlirAttributes.push_back(
1467 ArrayAttr::get(context, {keyAttr, StringAttr::get(context, val)}));
1468 continue;
1469 }
1470 if (attr.isIntAttribute()) {
1471 // For integer attributes, convert the value to a string and create a
1472 // [name, value] pair.
1473 auto val = std::to_string(attr.getValueAsInt());
1474 mlirAttributes.push_back(
1475 ArrayAttr::get(context, {keyAttr, StringAttr::get(context, val)}));
1476 continue;
1477 }
1478 if (attr.isEnumAttribute()) {
1479 // For enum attributes, add only the attribute name.
1480 mlirAttributes.push_back(keyAttr);
1481 continue;
1482 }
1483
1484 emitWarning(loc)
1485 << "'" << attrName
1486 << "' attribute is invalid on current operation, skipping it";
1487 }
1488 return ArrayAttr::get(context, mlirAttributes);
1489}
1490
1491/// Converts LLVM attributes from `globalVar` into MLIR attributes and adds them
1492/// to `globalOp` as target-specific attributes.
1493static void processTargetSpecificAttrs(llvm::GlobalVariable *globalVar,
1494 GlobalOp globalOp) {
1495 ArrayAttr targetSpecificAttrs = convertLLVMAttributesToMLIR(
1496 globalOp.getLoc(), globalOp.getContext(), globalVar->getAttributes());
1497 if (!targetSpecificAttrs.empty())
1498 globalOp.setTargetSpecificAttrsAttr(targetSpecificAttrs);
1499}
1500
1501LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) {
1502 // Insert the global after the last one or at the start of the module.
1503 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1504
1505 Attribute valueAttr;
1506 if (globalVar->hasInitializer())
1507 valueAttr = getConstantAsAttr(globalVar->getInitializer());
1508 Type type = convertType(globalVar->getValueType());
1509
1510 uint64_t alignment = 0;
1511 llvm::MaybeAlign maybeAlign = globalVar->getAlign();
1512 if (maybeAlign.has_value()) {
1513 llvm::Align align = *maybeAlign;
1514 alignment = align.value();
1515 }
1516
1517 // Get the global expression associated with this global variable and convert
1518 // it.
1519 SmallVector<Attribute> globalExpressionAttrs;
1520 SmallVector<llvm::DIGlobalVariableExpression *> globalExpressions;
1521 globalVar->getDebugInfo(globalExpressions);
1522
1523 for (llvm::DIGlobalVariableExpression *expr : globalExpressions) {
1524 DIGlobalVariableExpressionAttr globalExpressionAttr =
1525 debugImporter->translateGlobalVariableExpression(expr);
1526 globalExpressionAttrs.push_back(globalExpressionAttr);
1527 }
1528
1529 // Workaround to support LLVM's nameless globals. MLIR, in contrast to LLVM,
1530 // always requires a symbol name.
1531 StringRef globalName = globalVar->getName();
1532 if (globalName.empty())
1533 globalName = getOrCreateNamelessSymbolName(globalVar).getValue();
1534
1535 GlobalOp globalOp = GlobalOp::create(
1536 builder, mlirModule.getLoc(), type, globalVar->isConstant(),
1537 convertLinkageFromLLVM(globalVar->getLinkage()), StringRef(globalName),
1538 valueAttr, alignment, /*addrSpace=*/globalVar->getAddressSpace(),
1539 /*dsoLocal=*/globalVar->isDSOLocal(),
1540 /*thread_local=*/globalVar->isThreadLocal(), /*comdat=*/SymbolRefAttr(),
1541 /*attrs=*/ArrayRef<NamedAttribute>(), /*dbgExprs=*/globalExpressionAttrs);
1542 globalInsertionOp = globalOp;
1543
1544 if (globalVar->hasInitializer() && !valueAttr) {
1545 clearRegionState();
1546 Block *block = builder.createBlock(&globalOp.getInitializerRegion());
1547 setConstantInsertionPointToStart(block);
1548 FailureOr<Value> initializer =
1549 convertConstantExpr(globalVar->getInitializer());
1550 if (failed(initializer))
1551 return failure();
1552 ReturnOp::create(builder, globalOp.getLoc(), *initializer);
1553 }
1554 if (globalVar->hasAtLeastLocalUnnamedAddr()) {
1555 globalOp.setUnnamedAddr(
1556 convertUnnamedAddrFromLLVM(globalVar->getUnnamedAddr()));
1557 }
1558 if (globalVar->hasSection())
1559 globalOp.setSection(globalVar->getSection());
1560 globalOp.setVisibility_(
1561 convertVisibilityFromLLVM(globalVar->getVisibility()));
1562
1563 if (globalVar->hasComdat())
1564 globalOp.setComdatAttr(comdatMapping.lookup(globalVar->getComdat()));
1565
1566 processTargetSpecificAttrs(globalVar, globalOp);
1567
1568 return success();
1569}
1570
1571LogicalResult
1572ModuleImport::convertGlobalCtorsAndDtors(llvm::GlobalVariable *globalVar) {
1573 if (!globalVar->hasInitializer() || !globalVar->hasAppendingLinkage())
1574 return failure();
1575 llvm::Constant *initializer = globalVar->getInitializer();
1576
1577 bool knownInit = isa<llvm::ConstantArray>(initializer) ||
1578 isa<llvm::ConstantAggregateZero>(initializer);
1579 if (!knownInit)
1580 return failure();
1581
1582 // ConstantAggregateZero does not engage with the operand initialization
1583 // in the loop that follows - there should be no operands. This implies
1584 // empty ctor/dtor lists.
1585 if (auto *caz = dyn_cast<llvm::ConstantAggregateZero>(initializer)) {
1586 if (caz->getElementCount().getFixedValue() != 0)
1587 return failure();
1588 }
1589
1590 SmallVector<Attribute> funcs;
1591 SmallVector<int32_t> priorities;
1592 SmallVector<Attribute> dataList;
1593 for (llvm::Value *operand : initializer->operands()) {
1594 auto *aggregate = dyn_cast<llvm::ConstantAggregate>(operand);
1595 if (!aggregate || aggregate->getNumOperands() != 3)
1596 return failure();
1597
1598 auto *priority = dyn_cast<llvm::ConstantInt>(aggregate->getOperand(0));
1599 auto *func = dyn_cast<llvm::Function>(aggregate->getOperand(1));
1600 auto *data = dyn_cast<llvm::Constant>(aggregate->getOperand(2));
1601 if (!priority || !func || !data)
1602 return failure();
1603
1604 auto *gv = dyn_cast_or_null<llvm::GlobalValue>(data);
1605 Attribute dataAttr;
1606 if (gv)
1607 dataAttr = FlatSymbolRefAttr::get(context, gv->getName());
1608 else if (data->isNullValue())
1609 dataAttr = ZeroAttr::get(context);
1610 else
1611 return failure();
1612
1613 funcs.push_back(FlatSymbolRefAttr::get(context, func->getName()));
1614 priorities.push_back(priority->getValue().getZExtValue());
1615 dataList.push_back(dataAttr);
1616 }
1617
1618 // Insert the global after the last one or at the start of the module.
1619 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1620
1621 if (globalVar->getName() == getGlobalCtorsVarName()) {
1622 globalInsertionOp = LLVM::GlobalCtorsOp::create(
1623 builder, mlirModule.getLoc(), builder.getArrayAttr(funcs),
1624 builder.getI32ArrayAttr(priorities), builder.getArrayAttr(dataList));
1625 return success();
1626 }
1627 globalInsertionOp = LLVM::GlobalDtorsOp::create(
1628 builder, mlirModule.getLoc(), builder.getArrayAttr(funcs),
1629 builder.getI32ArrayAttr(priorities), builder.getArrayAttr(dataList));
1630 return success();
1631}
1632
1634ModuleImport::getConstantsToConvert(llvm::Constant *constant) {
1635 // Return the empty set if the constant has been translated before.
1636 if (valueMapping.contains(constant))
1637 return {};
1638
1639 // Traverse the constants in post-order and stop the traversal if a constant
1640 // already has a `valueMapping` from an earlier constant translation or if the
1641 // constant is traversed a second time.
1642 SetVector<llvm::Constant *> orderedSet;
1645 workList.insert(constant);
1646 while (!workList.empty()) {
1647 llvm::Constant *current = workList.back();
1648 // References of global objects are just pointers to the object. Avoid
1649 // walking the elements of these here.
1650 if (isa<llvm::GlobalObject>(current) || isa<llvm::GlobalAlias>(current)) {
1651 orderedSet.insert(current);
1652 workList.pop_back();
1653 continue;
1654 }
1655
1656 // Collect all dependencies of the current constant and add them to the
1657 // adjacency list if none has been computed before.
1658 auto [adjacencyIt, inserted] = adjacencyLists.try_emplace(current);
1659 if (inserted) {
1660 // Add all constant operands to the adjacency list and skip any other
1661 // values such as basic block addresses.
1662 for (llvm::Value *operand : current->operands())
1663 if (auto *constDependency = dyn_cast<llvm::Constant>(operand))
1664 adjacencyIt->getSecond().push_back(constDependency);
1665 // Use the getElementValue method to add the dependencies of zero
1666 // initialized aggregate constants since they do not take any operands.
1667 if (auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(current)) {
1668 unsigned numElements = constAgg->getElementCount().getFixedValue();
1669 for (unsigned i = 0, e = numElements; i != e; ++i)
1670 adjacencyIt->getSecond().push_back(constAgg->getElementValue(i));
1671 }
1672 }
1673 // Add the current constant to the `orderedSet` of the traversed nodes if
1674 // all its dependencies have been traversed before. Additionally, remove the
1675 // constant from the `workList` and continue the traversal.
1676 if (adjacencyIt->getSecond().empty()) {
1677 orderedSet.insert(current);
1678 workList.pop_back();
1679 continue;
1680 }
1681 // Add the next dependency from the adjacency list to the `workList` and
1682 // continue the traversal. Remove the dependency from the adjacency list to
1683 // mark that it has been processed. Only enqueue the dependency if it has no
1684 // `valueMapping` from an earlier translation and if it has not been
1685 // enqueued before.
1686 llvm::Constant *dependency = adjacencyIt->getSecond().pop_back_val();
1687 if (valueMapping.contains(dependency) || workList.contains(dependency) ||
1688 orderedSet.contains(dependency))
1689 continue;
1690 workList.insert(dependency);
1691 }
1692
1693 return orderedSet;
1694}
1695
1696FailureOr<Value> ModuleImport::convertConstant(llvm::Constant *constant) {
1697 Location loc = UnknownLoc::get(context);
1698
1699 // Convert constants that can be represented as attributes.
1700 if (Attribute attr = getConstantAsAttr(constant)) {
1701 Type type = convertType(constant->getType());
1702 if (auto symbolRef = dyn_cast<FlatSymbolRefAttr>(attr)) {
1703 return AddressOfOp::create(builder, loc, type, symbolRef.getValue())
1704 .getResult();
1705 }
1706 return ConstantOp::create(builder, loc, type, attr).getResult();
1707 }
1708
1709 // Convert null pointer constants.
1710 if (auto *nullPtr = dyn_cast<llvm::ConstantPointerNull>(constant)) {
1711 Type type = convertType(nullPtr->getType());
1712 return ZeroOp::create(builder, loc, type).getResult();
1713 }
1714
1715 // Convert none token constants.
1716 if (isa<llvm::ConstantTokenNone>(constant)) {
1717 return NoneTokenOp::create(builder, loc).getResult();
1718 }
1719
1720 // Convert poison.
1721 if (auto *poisonVal = dyn_cast<llvm::PoisonValue>(constant)) {
1722 Type type = convertType(poisonVal->getType());
1723 return PoisonOp::create(builder, loc, type).getResult();
1724 }
1725
1726 // Convert undef.
1727 if (auto *undefVal = dyn_cast<llvm::UndefValue>(constant)) {
1728 Type type = convertType(undefVal->getType());
1729 return UndefOp::create(builder, loc, type).getResult();
1730 }
1731
1732 // Convert dso_local_equivalent.
1733 if (auto *dsoLocalEquivalent = dyn_cast<llvm::DSOLocalEquivalent>(constant)) {
1734 Type type = convertType(dsoLocalEquivalent->getType());
1735 return DSOLocalEquivalentOp::create(
1736 builder, loc, type,
1738 builder.getContext(),
1739 dsoLocalEquivalent->getGlobalValue()->getName()))
1740 .getResult();
1741 }
1742
1743 // Convert global variable accesses.
1744 if (auto *globalObj = dyn_cast<llvm::GlobalObject>(constant)) {
1745 Type type = convertType(globalObj->getType());
1746 StringRef globalName = globalObj->getName();
1747 FlatSymbolRefAttr symbolRef;
1748 // Empty names are only allowed for global variables.
1749 if (globalName.empty())
1750 symbolRef =
1751 getOrCreateNamelessSymbolName(cast<llvm::GlobalVariable>(globalObj));
1752 else
1753 symbolRef = FlatSymbolRefAttr::get(context, globalName);
1754 return AddressOfOp::create(builder, loc, type, symbolRef).getResult();
1755 }
1756
1757 // Convert global alias accesses.
1758 if (auto *globalAliasObj = dyn_cast<llvm::GlobalAlias>(constant)) {
1759 Type type = convertType(globalAliasObj->getType());
1760 StringRef aliaseeName = globalAliasObj->getName();
1761 FlatSymbolRefAttr symbolRef = FlatSymbolRefAttr::get(context, aliaseeName);
1762 return AddressOfOp::create(builder, loc, type, symbolRef).getResult();
1763 }
1764
1765 // Convert constant expressions.
1766 if (auto *constExpr = dyn_cast<llvm::ConstantExpr>(constant)) {
1767 // Convert the constant expression to a temporary LLVM instruction and
1768 // translate it using the `processInstruction` method. Delete the
1769 // instruction after the translation and remove it from `valueMapping`,
1770 // since later calls to `getAsInstruction` may return the same address
1771 // resulting in a conflicting `valueMapping` entry.
1772 llvm::Instruction *inst = constExpr->getAsInstruction();
1773 llvm::scope_exit guard([&]() {
1774 assert(!noResultOpMapping.contains(inst) &&
1775 "expected constant expression to return a result");
1776 valueMapping.erase(inst);
1777 inst->deleteValue();
1778 });
1779 // Note: `processInstruction` does not call `convertConstant` recursively
1780 // since all constant dependencies have been converted before.
1781 assert(llvm::all_of(inst->operands(), [&](llvm::Value *value) {
1782 return valueMapping.contains(value);
1783 }));
1784 if (failed(processInstruction(inst)))
1785 return failure();
1786 return lookupValue(inst);
1787 }
1788
1789 // Convert zero-initialized aggregates to ZeroOp.
1790 if (auto *aggregateZero = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1791 Type type = convertType(aggregateZero->getType());
1792 return ZeroOp::create(builder, loc, type).getResult();
1793 }
1794
1795 // Convert aggregate constants.
1796 if (auto *constAgg = dyn_cast<llvm::ConstantAggregate>(constant)) {
1797 // Lookup the aggregate elements that have been converted before.
1798 SmallVector<Value> elementValues;
1799
1800 elementValues.reserve(constAgg->getNumOperands());
1801 for (llvm::Value *operand : constAgg->operands())
1802 elementValues.push_back(lookupValue(operand));
1803
1804 assert(llvm::count(elementValues, nullptr) == 0 &&
1805 "expected all elements have been converted before");
1806
1807 // Generate an UndefOp as root value and insert the aggregate elements.
1808 Type rootType = convertType(constant->getType());
1809 bool isArrayOrStruct = isa<LLVMArrayType, LLVMStructType>(rootType);
1810 assert((isArrayOrStruct || LLVM::isCompatibleVectorType(rootType)) &&
1811 "unrecognized aggregate type");
1812 Value root = UndefOp::create(builder, loc, rootType);
1813 for (const auto &it : llvm::enumerate(elementValues)) {
1814 if (isArrayOrStruct) {
1815 root =
1816 InsertValueOp::create(builder, loc, root, it.value(), it.index());
1817 } else {
1818 Attribute indexAttr = builder.getI32IntegerAttr(it.index());
1819 Value indexValue =
1820 ConstantOp::create(builder, loc, builder.getI32Type(), indexAttr);
1821 root = InsertElementOp::create(builder, loc, rootType, root, it.value(),
1822 indexValue);
1823 }
1824 }
1825 return root;
1826 }
1827
1828 if (auto *constTargetNone = dyn_cast<llvm::ConstantTargetNone>(constant)) {
1829 LLVMTargetExtType targetExtType =
1830 cast<LLVMTargetExtType>(convertType(constTargetNone->getType()));
1831 assert(targetExtType.hasProperty(LLVMTargetExtType::HasZeroInit) &&
1832 "target extension type does not support zero-initialization");
1833 // Create llvm.mlir.zero operation to represent zero-initialization of
1834 // target extension type.
1835 return LLVM::ZeroOp::create(builder, loc, targetExtType).getRes();
1836 }
1837
1838 if (auto *blockAddr = dyn_cast<llvm::BlockAddress>(constant)) {
1839 auto fnSym =
1840 FlatSymbolRefAttr::get(context, blockAddr->getFunction()->getName());
1841 auto blockTag =
1842 BlockTagAttr::get(context, blockAddr->getBasicBlock()->getNumber());
1843 return BlockAddressOp::create(
1844 builder, loc, convertType(blockAddr->getType()),
1845 BlockAddressAttr::get(context, fnSym, blockTag))
1846 .getRes();
1847 }
1848
1849 StringRef error = "";
1850
1851 if (isa<llvm::ConstantPtrAuth>(constant))
1852 error = " since ptrauth(...) is unsupported";
1853
1854 if (isa<llvm::NoCFIValue>(constant))
1855 error = " since no_cfi is unsupported";
1856
1857 if (isa<llvm::GlobalValue>(constant))
1858 error = " since global value is unsupported";
1859
1860 return emitError(loc) << "unhandled constant: " << diag(*constant) << error;
1861}
1862
1863FailureOr<Value> ModuleImport::convertConstantExpr(llvm::Constant *constant) {
1864 // Only call the function for constants that have not been translated before
1865 // since it updates the constant insertion point assuming the converted
1866 // constant has been introduced at the end of the constant section.
1867 assert(!valueMapping.contains(constant) &&
1868 "expected constant has not been converted before");
1869 assert(constantInsertionBlock &&
1870 "expected the constant insertion block to be non-null");
1871
1872 // Insert the constant after the last one or at the start of the entry block.
1873 OpBuilder::InsertionGuard guard(builder);
1874 if (!constantInsertionOp)
1875 builder.setInsertionPointToStart(constantInsertionBlock);
1876 else
1877 builder.setInsertionPointAfter(constantInsertionOp);
1878
1879 // Convert all constants of the expression and add them to `valueMapping`.
1880 SetVector<llvm::Constant *> constantsToConvert =
1881 getConstantsToConvert(constant);
1882 for (llvm::Constant *constantToConvert : constantsToConvert) {
1883 FailureOr<Value> converted = convertConstant(constantToConvert);
1884 if (failed(converted))
1885 return failure();
1886 mapValue(constantToConvert, *converted);
1887 }
1888
1889 // Update the constant insertion point and return the converted constant.
1890 Value result = lookupValue(constant);
1891 constantInsertionOp = result.getDefiningOp();
1892 return result;
1893}
1894
1895FailureOr<Value> ModuleImport::convertValue(llvm::Value *value) {
1896 assert(!isa<llvm::MetadataAsValue>(value) &&
1897 "expected value to not be metadata");
1898
1899 // Return the mapped value if it has been converted before.
1900 auto it = valueMapping.find(value);
1901 if (it != valueMapping.end())
1902 return it->getSecond();
1903
1904 // Convert constants such as immediate values that have no mapping yet.
1905 if (auto *constant = dyn_cast<llvm::Constant>(value))
1906 return convertConstantExpr(constant);
1907
1908 Location loc = UnknownLoc::get(context);
1909 if (auto *inst = dyn_cast<llvm::Instruction>(value))
1910 loc = translateLoc(inst->getDebugLoc());
1911 return emitError(loc) << "unhandled value: " << diag(*value);
1912}
1913
1914FailureOr<Value> ModuleImport::convertMetadataValue(llvm::Value *value) {
1915 // A value may be wrapped as metadata, for example, when passed to a debug
1916 // intrinsic. Unwrap these values before the conversion.
1917 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
1918 if (!nodeAsVal)
1919 return failure();
1920 auto *node = dyn_cast<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
1921 if (!node)
1922 return failure();
1923 value = node->getValue();
1924
1925 // Return the mapped value if it has been converted before.
1926 auto it = valueMapping.find(value);
1927 if (it != valueMapping.end())
1928 return it->getSecond();
1929
1930 // Convert constants such as immediate values that have no mapping yet.
1931 if (auto *constant = dyn_cast<llvm::Constant>(value))
1932 return convertConstantExpr(constant);
1933 return failure();
1934}
1935
1936FailureOr<SmallVector<Value>>
1938 SmallVector<Value> remapped;
1939 remapped.reserve(values.size());
1940 for (llvm::Value *value : values) {
1941 FailureOr<Value> converted = convertValue(value);
1942 if (failed(converted))
1943 return failure();
1944 remapped.push_back(*converted);
1945 }
1946 return remapped;
1947}
1948
1951 bool requiresOpBundles, ArrayRef<unsigned> immArgPositions,
1952 ArrayRef<StringLiteral> immArgAttrNames, SmallVectorImpl<Value> &valuesOut,
1954 assert(immArgPositions.size() == immArgAttrNames.size() &&
1955 "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "
1956 "length");
1957
1958 SmallVector<llvm::Value *> operands(values);
1959 for (auto [immArgPos, immArgName] :
1960 llvm::zip(immArgPositions, immArgAttrNames)) {
1961 auto &value = operands[immArgPos];
1962 auto *constant = llvm::cast<llvm::Constant>(value);
1963 auto attr = getScalarConstantAsAttr(builder, constant);
1964 assert(attr && attr.getType().isIntOrFloat() &&
1965 "expected immarg to be float or integer constant");
1966 auto nameAttr = StringAttr::get(attr.getContext(), immArgName);
1967 attrsOut.push_back({nameAttr, attr});
1968 // Mark matched attribute values as null (so they can be removed below).
1969 value = nullptr;
1970 }
1971
1972 for (llvm::Value *value : operands) {
1973 if (!value)
1974 continue;
1975 auto mlirValue = convertValue(value);
1976 if (failed(mlirValue))
1977 return failure();
1978 valuesOut.push_back(*mlirValue);
1979 }
1980
1981 SmallVector<int> opBundleSizes;
1982 SmallVector<Attribute> opBundleTagAttrs;
1983 if (requiresOpBundles) {
1984 opBundleSizes.reserve(opBundles.size());
1985 opBundleTagAttrs.reserve(opBundles.size());
1986
1987 for (const llvm::OperandBundleUse &bundle : opBundles) {
1988 opBundleSizes.push_back(bundle.Inputs.size());
1989 opBundleTagAttrs.push_back(StringAttr::get(context, bundle.getTagName()));
1990
1991 for (const llvm::Use &opBundleOperand : bundle.Inputs) {
1992 auto operandMlirValue = convertValue(opBundleOperand.get());
1993 if (failed(operandMlirValue))
1994 return failure();
1995 valuesOut.push_back(*operandMlirValue);
1996 }
1997 }
1998
1999 auto opBundleSizesAttr = DenseI32ArrayAttr::get(context, opBundleSizes);
2000 auto opBundleSizesAttrNameAttr =
2001 StringAttr::get(context, LLVMDialect::getOpBundleSizesAttrName());
2002 attrsOut.push_back({opBundleSizesAttrNameAttr, opBundleSizesAttr});
2003
2004 auto opBundleTagsAttr = ArrayAttr::get(context, opBundleTagAttrs);
2005 auto opBundleTagsAttrNameAttr =
2006 StringAttr::get(context, LLVMDialect::getOpBundleTagsAttrName());
2007 attrsOut.push_back({opBundleTagsAttrNameAttr, opBundleTagsAttr});
2008 }
2009
2010 return success();
2011}
2012
2013IntegerAttr ModuleImport::matchIntegerAttr(llvm::Value *value) {
2014 IntegerAttr integerAttr;
2015 FailureOr<Value> converted = convertValue(value);
2016 bool success = succeeded(converted) &&
2017 matchPattern(*converted, m_Constant(&integerAttr));
2018 assert(success && "expected a constant integer value");
2019 (void)success;
2020 return integerAttr;
2021}
2022
2023FloatAttr ModuleImport::matchFloatAttr(llvm::Value *value) {
2024 FloatAttr floatAttr;
2025 FailureOr<Value> converted = convertValue(value);
2026 bool success =
2027 succeeded(converted) && matchPattern(*converted, m_Constant(&floatAttr));
2028 assert(success && "expected a constant float value");
2029 (void)success;
2030 return floatAttr;
2031}
2032
2035 llvm::DILocalVariable *node = nullptr;
2036 if (auto *value = dyn_cast<llvm::Value *>(valOrVariable)) {
2037 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2038 node = cast<llvm::DILocalVariable>(nodeAsVal->getMetadata());
2039 } else {
2040 node = cast<llvm::DILocalVariable *>(valOrVariable);
2041 }
2042 return debugImporter->translate(node);
2043}
2044
2045DILabelAttr ModuleImport::matchLabelAttr(llvm::Value *value) {
2046 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2047 auto *node = cast<llvm::DILabel>(nodeAsVal->getMetadata());
2048 return debugImporter->translate(node);
2049}
2050
2051FPExceptionBehaviorAttr
2053 auto *metadata = cast<llvm::MetadataAsValue>(value);
2054 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
2055 std::optional<llvm::fp::ExceptionBehavior> optLLVM =
2056 llvm::convertStrToExceptionBehavior(mdstr->getString());
2057 assert(optLLVM && "Expecting FP exception behavior");
2058 return builder.getAttr<FPExceptionBehaviorAttr>(
2059 convertFPExceptionBehaviorFromLLVM(*optLLVM));
2060}
2061
2062RoundingModeAttr ModuleImport::matchRoundingModeAttr(llvm::Value *value) {
2063 auto *metadata = cast<llvm::MetadataAsValue>(value);
2064 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
2065 std::optional<llvm::RoundingMode> optLLVM =
2066 llvm::convertStrToRoundingMode(mdstr->getString());
2067 assert(optLLVM && "Expecting rounding mode");
2068 return builder.getAttr<RoundingModeAttr>(
2069 convertRoundingModeFromLLVM(*optLLVM));
2070}
2071
2072FailureOr<SmallVector<AliasScopeAttr>>
2074 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2075 auto *node = cast<llvm::MDNode>(nodeAsVal->getMetadata());
2076 return lookupAliasScopeAttrs(node);
2077}
2078
2079Location ModuleImport::translateLoc(llvm::DILocation *loc) {
2080 return debugImporter->translateLoc(loc);
2081}
2082
2083LogicalResult
2084ModuleImport::convertBranchArgs(llvm::Instruction *branch,
2085 llvm::BasicBlock *target,
2086 SmallVectorImpl<Value> &blockArguments) {
2087 for (auto inst = target->begin(); isa<llvm::PHINode>(inst); ++inst) {
2088 auto *phiInst = cast<llvm::PHINode>(&*inst);
2089 llvm::Value *value = phiInst->getIncomingValueForBlock(branch->getParent());
2090 FailureOr<Value> converted = convertValue(value);
2091 if (failed(converted))
2092 return failure();
2093 blockArguments.push_back(*converted);
2094 }
2095 return success();
2096}
2097
2098FailureOr<SmallVector<Value>>
2099ModuleImport::convertCallOperands(llvm::CallBase *callInst,
2100 bool allowInlineAsm) {
2101 bool isInlineAsm = callInst->isInlineAsm();
2102 if (isInlineAsm && !allowInlineAsm)
2103 return failure();
2104
2105 SmallVector<Value> operands;
2106
2107 // Cannot use isIndirectCall() here because we need to handle Constant callees
2108 // that are not considered indirect calls by LLVM. However, in MLIR, they are
2109 // treated as indirect calls to constant operands that need to be converted.
2110 // Skip the callee operand if it's inline assembly, as it's handled separately
2111 // in InlineAsmOp.
2112 llvm::Value *calleeOperand = callInst->getCalledOperand();
2113 if (!isa<llvm::Function, llvm::GlobalIFunc>(calleeOperand) && !isInlineAsm) {
2114 FailureOr<Value> called = convertValue(calleeOperand);
2115 if (failed(called))
2116 return failure();
2117 operands.push_back(*called);
2118 }
2119
2120 SmallVector<llvm::Value *> args(callInst->args());
2121 FailureOr<SmallVector<Value>> arguments = convertValues(args);
2122 if (failed(arguments))
2123 return failure();
2124
2125 llvm::append_range(operands, *arguments);
2126 return operands;
2127}
2128
2129/// Checks if `callType` and `calleeType` are compatible and can be represented
2130/// in MLIR.
2131static LogicalResult
2132checkFunctionTypeCompatibility(LLVMFunctionType callType,
2133 LLVMFunctionType calleeType) {
2134 if (callType.getReturnType() != calleeType.getReturnType())
2135 return failure();
2136
2137 if (calleeType.isVarArg()) {
2138 // For variadic functions, the call can have more types than the callee
2139 // specifies.
2140 if (callType.getNumParams() < calleeType.getNumParams())
2141 return failure();
2142 } else {
2143 // For non-variadic functions, the number of parameters needs to be the
2144 // same.
2145 if (callType.getNumParams() != calleeType.getNumParams())
2146 return failure();
2147 }
2148
2149 // Check that all operands match.
2150 for (auto [operandType, argumentType] :
2151 llvm::zip(callType.getParams(), calleeType.getParams()))
2152 if (operandType != argumentType)
2153 return failure();
2154
2155 return success();
2156}
2157
2158FailureOr<LLVMFunctionType>
2159ModuleImport::convertFunctionType(llvm::CallBase *callInst,
2160 bool &isIncompatibleCall) {
2161 isIncompatibleCall = false;
2162 auto castOrFailure = [](Type convertedType) -> FailureOr<LLVMFunctionType> {
2163 auto funcTy = dyn_cast_or_null<LLVMFunctionType>(convertedType);
2164 if (!funcTy)
2165 return failure();
2166 return funcTy;
2167 };
2168
2169 llvm::Value *calledOperand = callInst->getCalledOperand();
2170 FailureOr<LLVMFunctionType> callType =
2171 castOrFailure(convertType(callInst->getFunctionType()));
2172 if (failed(callType))
2173 return failure();
2174 auto *callee = dyn_cast<llvm::Function>(calledOperand);
2175
2176 llvm::FunctionType *origCalleeType = nullptr;
2177 if (callee) {
2178 origCalleeType = callee->getFunctionType();
2179 } else if (auto *ifunc = dyn_cast<llvm::GlobalIFunc>(calledOperand)) {
2180 origCalleeType = cast<llvm::FunctionType>(ifunc->getValueType());
2181 }
2182
2183 // For indirect calls, return the type of the call itself.
2184 if (!origCalleeType)
2185 return callType;
2186
2187 FailureOr<LLVMFunctionType> calleeType =
2188 castOrFailure(convertType(origCalleeType));
2189 if (failed(calleeType))
2190 return failure();
2191
2192 // Compare the types and notify users via `isIncompatibleCall` if they are not
2193 // compatible.
2194 if (failed(checkFunctionTypeCompatibility(*callType, *calleeType))) {
2195 isIncompatibleCall = true;
2196 Location loc = translateLoc(callInst->getDebugLoc());
2197 emitWarning(loc) << "incompatible call and callee types: " << *callType
2198 << " and " << *calleeType;
2199 return callType;
2200 }
2201
2202 return calleeType;
2203}
2204
2205FlatSymbolRefAttr ModuleImport::convertCalleeName(llvm::CallBase *callInst) {
2206 llvm::Value *calledOperand = callInst->getCalledOperand();
2207 if (isa<llvm::Function, llvm::GlobalIFunc>(calledOperand))
2208 return SymbolRefAttr::get(context, calledOperand->getName());
2209 return {};
2210}
2211
2212LogicalResult ModuleImport::convertIntrinsic(llvm::CallInst *inst) {
2213 if (succeeded(iface.convertIntrinsic(builder, inst, *this)))
2214 return success();
2215
2216 Location loc = translateLoc(inst->getDebugLoc());
2217 return emitError(loc) << "unhandled intrinsic: " << diag(*inst);
2218}
2219
2221ModuleImport::convertAsmInlineOperandAttrs(const llvm::CallBase &llvmCall) {
2222 const auto *ia = cast<llvm::InlineAsm>(llvmCall.getCalledOperand());
2223 unsigned argIdx = 0;
2224 SmallVector<mlir::Attribute> opAttrs;
2225 bool hasIndirect = false;
2226
2227 for (const llvm::InlineAsm::ConstraintInfo &ci : ia->ParseConstraints()) {
2228 // Only deal with constraints that correspond to call arguments.
2229 if (ci.Type == llvm::InlineAsm::isLabel || !ci.hasArg())
2230 continue;
2231
2232 // Only increment `argIdx` in terms of constraints containing arguments,
2233 // which are guaranteed to happen in the same order of the call arguments.
2234 if (ci.isIndirect) {
2235 if (llvm::Type *paramEltType = llvmCall.getParamElementType(argIdx)) {
2236 SmallVector<mlir::NamedAttribute> attrs;
2237 attrs.push_back(builder.getNamedAttr(
2238 mlir::LLVM::InlineAsmOp::getElementTypeAttrName(),
2239 mlir::TypeAttr::get(convertType(paramEltType))));
2240 opAttrs.push_back(builder.getDictionaryAttr(attrs));
2241 hasIndirect = true;
2242 }
2243 } else {
2244 opAttrs.push_back(builder.getDictionaryAttr({}));
2245 }
2246 argIdx++;
2247 }
2248
2249 // Avoid emitting an array where all entries are empty dictionaries.
2250 return hasIndirect ? ArrayAttr::get(mlirModule->getContext(), opAttrs)
2251 : nullptr;
2252}
2253
2254LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
2255 // Convert all instructions that do not provide an MLIR builder.
2256 Location loc = translateLoc(inst->getDebugLoc());
2257 if (auto *brInst = dyn_cast<llvm::UncondBrInst>(inst)) {
2258 llvm::BasicBlock *succ = brInst->getSuccessor();
2259 SmallVector<Value> blockArgs;
2260 if (failed(convertBranchArgs(brInst, succ, blockArgs)))
2261 return failure();
2262
2263 auto brOp = LLVM::BrOp::create(builder, loc, blockArgs, lookupBlock(succ));
2264 mapNoResultOp(inst, brOp);
2265 return success();
2266 }
2267 if (auto *brInst = dyn_cast<llvm::CondBrInst>(inst)) {
2268 SmallVector<Block *> succBlocks;
2269 SmallVector<SmallVector<Value>> succBlockArgs;
2270 for (auto i : llvm::seq<unsigned>(0, brInst->getNumSuccessors())) {
2271 llvm::BasicBlock *succ = brInst->getSuccessor(i);
2272 SmallVector<Value> blockArgs;
2273 if (failed(convertBranchArgs(brInst, succ, blockArgs)))
2274 return failure();
2275 succBlocks.push_back(lookupBlock(succ));
2276 succBlockArgs.push_back(blockArgs);
2277 }
2278
2279 FailureOr<Value> condition = convertValue(brInst->getCondition());
2280 if (failed(condition))
2281 return failure();
2282 auto condBrOp = LLVM::CondBrOp::create(
2283 builder, loc, *condition, succBlocks.front(), succBlockArgs.front(),
2284 succBlocks.back(), succBlockArgs.back());
2285 mapNoResultOp(inst, condBrOp);
2286 return success();
2287 }
2288 if (inst->getOpcode() == llvm::Instruction::Switch) {
2289 auto *swInst = cast<llvm::SwitchInst>(inst);
2290 // Process the condition value.
2291 FailureOr<Value> condition = convertValue(swInst->getCondition());
2292 if (failed(condition))
2293 return failure();
2294 SmallVector<Value> defaultBlockArgs;
2295 // Process the default case.
2296 llvm::BasicBlock *defaultBB = swInst->getDefaultDest();
2297 if (failed(convertBranchArgs(swInst, defaultBB, defaultBlockArgs)))
2298 return failure();
2299
2300 // Process the cases.
2301 unsigned numCases = swInst->getNumCases();
2302 SmallVector<SmallVector<Value>> caseOperands(numCases);
2303 SmallVector<ValueRange> caseOperandRefs(numCases);
2304 SmallVector<APInt> caseValues(numCases);
2305 SmallVector<Block *> caseBlocks(numCases);
2306 for (const auto &it : llvm::enumerate(swInst->cases())) {
2307 const llvm::SwitchInst::CaseHandle &caseHandle = it.value();
2308 llvm::BasicBlock *succBB = caseHandle.getCaseSuccessor();
2309 if (failed(convertBranchArgs(swInst, succBB, caseOperands[it.index()])))
2310 return failure();
2311 caseOperandRefs[it.index()] = caseOperands[it.index()];
2312 caseValues[it.index()] = caseHandle.getCaseValue()->getValue();
2313 caseBlocks[it.index()] = lookupBlock(succBB);
2314 }
2315
2316 auto switchOp = SwitchOp::create(builder, loc, *condition,
2317 lookupBlock(defaultBB), defaultBlockArgs,
2318 caseValues, caseBlocks, caseOperandRefs);
2319 mapNoResultOp(inst, switchOp);
2320 return success();
2321 }
2322 if (inst->getOpcode() == llvm::Instruction::PHI) {
2323 Type type = convertType(inst->getType());
2324 mapValue(inst, builder.getInsertionBlock()->addArgument(
2325 type, translateLoc(inst->getDebugLoc())));
2326 return success();
2327 }
2328 if (inst->getOpcode() == llvm::Instruction::Call) {
2329 auto *callInst = cast<llvm::CallInst>(inst);
2330 llvm::Value *calledOperand = callInst->getCalledOperand();
2331
2332 FailureOr<SmallVector<Value>> operands =
2333 convertCallOperands(callInst, /*allowInlineAsm=*/true);
2334 if (failed(operands))
2335 return failure();
2336
2337 auto callOp = [&]() -> FailureOr<Operation *> {
2338 if (auto *asmI = dyn_cast<llvm::InlineAsm>(calledOperand)) {
2339 Type resultTy = convertType(callInst->getType());
2340 if (!resultTy)
2341 return failure();
2342 ArrayAttr operandAttrs = convertAsmInlineOperandAttrs(*callInst);
2343 return InlineAsmOp::create(
2344 builder, loc, resultTy, *operands,
2345 builder.getStringAttr(asmI->getAsmString()),
2346 builder.getStringAttr(asmI->getConstraintString()),
2347 asmI->hasSideEffects(), asmI->isAlignStack(),
2348 convertTailCallKindFromLLVM(callInst->getTailCallKind()),
2349 AsmDialectAttr::get(
2350 mlirModule.getContext(),
2351 convertAsmDialectFromLLVM(asmI->getDialect())),
2352 operandAttrs)
2353 .getOperation();
2354 }
2355 bool isIncompatibleCall;
2356 FailureOr<LLVMFunctionType> funcTy =
2357 convertFunctionType(callInst, isIncompatibleCall);
2358 if (failed(funcTy))
2359 return failure();
2360
2361 FlatSymbolRefAttr callee = nullptr;
2362 if (isIncompatibleCall) {
2363 // Use an indirect call (in order to represent valid and verifiable LLVM
2364 // IR). Build the indirect call by passing an empty `callee` operand and
2365 // insert into `operands` to include the indirect call target.
2366 FlatSymbolRefAttr calleeSym = convertCalleeName(callInst);
2367 Value indirectCallVal = LLVM::AddressOfOp::create(
2368 builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);
2369 operands->insert(operands->begin(), indirectCallVal);
2370 } else {
2371 // Regular direct call using callee name.
2372 callee = convertCalleeName(callInst);
2373 }
2374 CallOp callOp = CallOp::create(builder, loc, *funcTy, callee, *operands);
2375
2376 if (failed(convertCallAttributes(callInst, callOp)))
2377 return failure();
2378
2379 // Handle parameter and result attributes unless it's an incompatible
2380 // call.
2381 if (!isIncompatibleCall)
2382 convertArgAndResultAttrs(callInst, callOp);
2383 return callOp.getOperation();
2384 }();
2385
2386 if (failed(callOp))
2387 return failure();
2388
2389 if (!callInst->getType()->isVoidTy())
2390 mapValue(inst, (*callOp)->getResult(0));
2391 else
2392 mapNoResultOp(inst, *callOp);
2393 return success();
2394 }
2395 if (inst->getOpcode() == llvm::Instruction::LandingPad) {
2396 auto *lpInst = cast<llvm::LandingPadInst>(inst);
2397
2398 SmallVector<Value> operands;
2399 operands.reserve(lpInst->getNumClauses());
2400 for (auto i : llvm::seq<unsigned>(0, lpInst->getNumClauses())) {
2401 FailureOr<Value> operand = convertValue(lpInst->getClause(i));
2402 if (failed(operand))
2403 return failure();
2404 operands.push_back(*operand);
2405 }
2406
2407 Type type = convertType(lpInst->getType());
2408 auto lpOp =
2409 LandingpadOp::create(builder, loc, type, lpInst->isCleanup(), operands);
2410 mapValue(inst, lpOp);
2411 return success();
2412 }
2413 if (inst->getOpcode() == llvm::Instruction::Invoke) {
2414 auto *invokeInst = cast<llvm::InvokeInst>(inst);
2415
2416 if (invokeInst->isInlineAsm())
2417 return emitError(loc) << "invoke of inline assembly is not supported";
2418
2419 FailureOr<SmallVector<Value>> operands = convertCallOperands(invokeInst);
2420 if (failed(operands))
2421 return failure();
2422
2423 // Check whether the invoke result is an argument to the normal destination
2424 // block.
2425 bool invokeResultUsedInPhi = llvm::any_of(
2426 invokeInst->getNormalDest()->phis(), [&](const llvm::PHINode &phi) {
2427 return phi.getIncomingValueForBlock(invokeInst->getParent()) ==
2428 invokeInst;
2429 });
2430
2431 Block *normalDest = lookupBlock(invokeInst->getNormalDest());
2432 Block *directNormalDest = normalDest;
2433 if (invokeResultUsedInPhi) {
2434 // The invoke result cannot be an argument to the normal destination
2435 // block, as that would imply using the invoke operation result in its
2436 // definition, so we need to create a dummy block to serve as an
2437 // intermediate destination.
2438 OpBuilder::InsertionGuard g(builder);
2439 directNormalDest = builder.createBlock(normalDest);
2440 }
2441
2442 SmallVector<Value> unwindArgs;
2443 if (failed(convertBranchArgs(invokeInst, invokeInst->getUnwindDest(),
2444 unwindArgs)))
2445 return failure();
2446
2447 bool isIncompatibleInvoke;
2448 FailureOr<LLVMFunctionType> funcTy =
2449 convertFunctionType(invokeInst, isIncompatibleInvoke);
2450 if (failed(funcTy))
2451 return failure();
2452
2453 FlatSymbolRefAttr calleeName = nullptr;
2454 if (isIncompatibleInvoke) {
2455 // Use an indirect invoke (in order to represent valid and verifiable LLVM
2456 // IR). Build the indirect invoke by passing an empty `callee` operand and
2457 // insert into `operands` to include the indirect invoke target.
2458 FlatSymbolRefAttr calleeSym = convertCalleeName(invokeInst);
2459 Value indirectInvokeVal = LLVM::AddressOfOp::create(
2460 builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);
2461 operands->insert(operands->begin(), indirectInvokeVal);
2462 } else {
2463 // Regular direct invoke using callee name.
2464 calleeName = convertCalleeName(invokeInst);
2465 }
2466 // Create the invoke operation. Normal destination block arguments will be
2467 // added later on to handle the case in which the operation result is
2468 // included in this list.
2469 auto invokeOp = InvokeOp::create(
2470 builder, loc, *funcTy, calleeName, *operands, directNormalDest,
2471 ValueRange(), lookupBlock(invokeInst->getUnwindDest()), unwindArgs);
2472
2473 if (failed(convertInvokeAttributes(invokeInst, invokeOp)))
2474 return failure();
2475
2476 // Handle parameter and result attributes unless it's an incompatible
2477 // invoke.
2478 if (!isIncompatibleInvoke)
2479 convertArgAndResultAttrs(invokeInst, invokeOp);
2480
2481 if (!invokeInst->getType()->isVoidTy())
2482 mapValue(inst, invokeOp.getResults().front());
2483 else
2484 mapNoResultOp(inst, invokeOp);
2485
2486 SmallVector<Value> normalArgs;
2487 if (failed(convertBranchArgs(invokeInst, invokeInst->getNormalDest(),
2488 normalArgs)))
2489 return failure();
2490
2491 if (invokeResultUsedInPhi) {
2492 // The dummy normal dest block will just host an unconditional branch
2493 // instruction to the normal destination block passing the required block
2494 // arguments (including the invoke operation's result).
2495 OpBuilder::InsertionGuard g(builder);
2496 builder.setInsertionPointToStart(directNormalDest);
2497 LLVM::BrOp::create(builder, loc, normalArgs, normalDest);
2498 } else {
2499 // If the invoke operation's result is not a block argument to the normal
2500 // destination block, just add the block arguments as usual.
2501 assert(llvm::none_of(
2502 normalArgs,
2503 [&](Value val) { return val.getDefiningOp() == invokeOp; }) &&
2504 "An llvm.invoke operation cannot pass its result as a block "
2505 "argument.");
2506 invokeOp.getNormalDestOperandsMutable().append(normalArgs);
2507 }
2508
2509 return success();
2510 }
2511 if (inst->getOpcode() == llvm::Instruction::GetElementPtr) {
2512 auto *gepInst = cast<llvm::GetElementPtrInst>(inst);
2513 Type sourceElementType = convertType(gepInst->getSourceElementType());
2514 FailureOr<Value> basePtr = convertValue(gepInst->getOperand(0));
2515 if (failed(basePtr))
2516 return failure();
2517
2518 // Treat every indices as dynamic since GEPOp::build will refine those
2519 // indices into static attributes later. One small downside of this
2520 // approach is that many unused `llvm.mlir.constant` would be emitted
2521 // at first place.
2522 SmallVector<GEPArg> indices;
2523 for (llvm::Value *operand : llvm::drop_begin(gepInst->operand_values())) {
2524 FailureOr<Value> index = convertValue(operand);
2525 if (failed(index))
2526 return failure();
2527 indices.push_back(*index);
2528 }
2529
2530 Type type = convertType(inst->getType());
2531 auto gepOp = GEPOp::create(
2532 builder, loc, type, sourceElementType, *basePtr, indices,
2533 static_cast<GEPNoWrapFlags>(gepInst->getNoWrapFlags().getRaw()));
2534 mapValue(inst, gepOp);
2535 return success();
2536 }
2537
2538 if (inst->getOpcode() == llvm::Instruction::IndirectBr) {
2539 auto *indBrInst = cast<llvm::IndirectBrInst>(inst);
2540
2541 FailureOr<Value> basePtr = convertValue(indBrInst->getAddress());
2542 if (failed(basePtr))
2543 return failure();
2544
2545 SmallVector<Block *> succBlocks;
2546 SmallVector<SmallVector<Value>> succBlockArgs;
2547 for (auto i : llvm::seq<unsigned>(0, indBrInst->getNumSuccessors())) {
2548 llvm::BasicBlock *succ = indBrInst->getSuccessor(i);
2549 SmallVector<Value> blockArgs;
2550 if (failed(convertBranchArgs(indBrInst, succ, blockArgs)))
2551 return failure();
2552 succBlocks.push_back(lookupBlock(succ));
2553 succBlockArgs.push_back(blockArgs);
2554 }
2555 SmallVector<ValueRange> succBlockArgsRange =
2556 llvm::to_vector_of<ValueRange>(succBlockArgs);
2557 Location loc = translateLoc(inst->getDebugLoc());
2558 auto indBrOp = LLVM::IndirectBrOp::create(builder, loc, *basePtr,
2559 succBlockArgsRange, succBlocks);
2560
2561 mapNoResultOp(inst, indBrOp);
2562 return success();
2563 }
2564
2565 // Convert all instructions that have an mlirBuilder.
2566 if (succeeded(convertInstructionImpl(builder, inst, *this, iface)))
2567 return success();
2568
2569 return emitError(loc) << "unhandled instruction: " << diag(*inst);
2570}
2571
2572LogicalResult ModuleImport::processInstruction(llvm::Instruction *inst) {
2573 // FIXME: Support uses of SubtargetData.
2574 // FIXME: Add support for call / operand attributes.
2575 // FIXME: Add support for the cleanupret, catchret, catchswitch, callbr,
2576 // vaarg, catchpad, cleanuppad instructions.
2577
2578 // Convert LLVM intrinsics calls to MLIR intrinsics.
2579 if (auto *intrinsic = dyn_cast<llvm::IntrinsicInst>(inst))
2580 return convertIntrinsic(intrinsic);
2581
2582 // Process debug records attached to this instruction. Debug variable records
2583 // are stored for later processing after all SSA values are converted, while
2584 // debug label records can be converted immediately.
2585 if (inst->DebugMarker) {
2586 for (llvm::DbgRecord &dbgRecord : inst->DebugMarker->getDbgRecordRange()) {
2587 // Store debug variable records for later processing.
2588 if (auto *dbgVariableRecord =
2589 dyn_cast<llvm::DbgVariableRecord>(&dbgRecord)) {
2590 addDebugRecord(dbgVariableRecord);
2591 continue;
2592 }
2593 Location loc = translateLoc(dbgRecord.getDebugLoc());
2594 auto emitUnsupportedWarning = [&]() -> LogicalResult {
2595 if (!emitExpensiveWarnings)
2596 return success();
2597 std::string options;
2598 llvm::raw_string_ostream optionsStream(options);
2599 dbgRecord.print(optionsStream);
2600 emitWarning(loc) << "unhandled debug record " << optionsStream.str();
2601 return success();
2602 };
2603 // Convert the debug label records in-place.
2604 if (auto *dbgLabelRecord = dyn_cast<llvm::DbgLabelRecord>(&dbgRecord)) {
2605 DILabelAttr labelAttr =
2606 debugImporter->translate(dbgLabelRecord->getLabel());
2607 if (!labelAttr)
2608 return emitUnsupportedWarning();
2609 LLVM::DbgLabelOp::create(builder, loc, labelAttr);
2610 continue;
2611 }
2612 // Warn if an unsupported debug record is encountered.
2613 return emitUnsupportedWarning();
2614 }
2615 }
2616
2617 // Convert all remaining LLVM instructions to MLIR operations.
2618 return convertInstruction(inst);
2619}
2620
2621FlatSymbolRefAttr ModuleImport::getPersonalityAsAttr(llvm::Function *f) {
2622 if (!f->hasPersonalityFn())
2623 return nullptr;
2624
2625 llvm::Constant *pf = f->getPersonalityFn();
2626
2627 // If it directly has a name, we can use it.
2628 if (pf->hasName())
2629 return SymbolRefAttr::get(builder.getContext(), pf->getName());
2630
2631 // If it doesn't have a name, currently, only function pointers that are
2632 // bitcast to i8* are parsed.
2633 if (auto *ce = dyn_cast<llvm::ConstantExpr>(pf)) {
2634 if (ce->getOpcode() == llvm::Instruction::BitCast &&
2635 ce->getType() == llvm::PointerType::getUnqual(f->getContext())) {
2636 if (auto *func = dyn_cast<llvm::Function>(ce->getOperand(0)))
2637 return SymbolRefAttr::get(builder.getContext(), func->getName());
2638 }
2639 }
2640 return FlatSymbolRefAttr();
2641}
2642
2643static void processMemoryEffects(llvm::Function *func, LLVMFuncOp funcOp) {
2644 llvm::MemoryEffects memEffects = func->getMemoryEffects();
2645
2646 auto othermem = convertModRefInfoFromLLVM(
2647 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
2648 auto argMem = convertModRefInfoFromLLVM(
2649 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
2650 auto inaccessibleMem = convertModRefInfoFromLLVM(
2651 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
2652 auto errnoMem = convertModRefInfoFromLLVM(
2653 memEffects.getModRef(llvm::MemoryEffects::Location::ErrnoMem));
2654 auto targetMem0 = convertModRefInfoFromLLVM(
2655 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem0));
2656 auto targetMem1 = convertModRefInfoFromLLVM(
2657 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem1));
2658 auto memAttr =
2659 MemoryEffectsAttr::get(funcOp.getContext(), othermem, argMem,
2660 inaccessibleMem, errnoMem, targetMem0, targetMem1);
2661 // Only set the attr when it does not match the default value.
2662 if (memAttr.isReadWrite())
2663 return;
2664 funcOp.setMemoryEffectsAttr(memAttr);
2665}
2666
2667static void processDenormalFPEnv(llvm::Function *func, LLVMFuncOp funcOp) {
2668 llvm::DenormalFPEnv denormalFpEnv = func->getDenormalFPEnv();
2669 // Only set the attr when it does not match the default value.
2670 if (denormalFpEnv == llvm::DenormalFPEnv::getDefault())
2671 return;
2672
2673 llvm::DenormalMode defaultMode = denormalFpEnv.DefaultMode;
2674 llvm::DenormalMode floatMode = denormalFpEnv.F32Mode;
2675
2676 auto denormalFpEnvAttr = DenormalFPEnvAttr::get(
2677 funcOp.getContext(), convertDenormalModeKindFromLLVM(defaultMode.Output),
2678 convertDenormalModeKindFromLLVM(defaultMode.Input),
2679 convertDenormalModeKindFromLLVM(floatMode.Output),
2680 convertDenormalModeKindFromLLVM(floatMode.Input));
2681 funcOp.setDenormalFpenvAttr(denormalFpEnvAttr);
2682}
2683
2684// List of LLVM IR attributes that map to an explicit attribute on the MLIR
2685// LLVMFuncOp.
2686static constexpr std::array kExplicitLLVMFuncOpAttributes{
2687 StringLiteral("aarch64_in_za"),
2688 StringLiteral("aarch64_inout_za"),
2689 StringLiteral("aarch64_new_za"),
2690 StringLiteral("aarch64_out_za"),
2691 StringLiteral("aarch64_preserves_za"),
2692 StringLiteral("aarch64_pstate_sm_body"),
2693 StringLiteral("aarch64_pstate_sm_compatible"),
2694 StringLiteral("aarch64_pstate_sm_enabled"),
2695 StringLiteral("allocsize"),
2696 StringLiteral("alwaysinline"),
2697 StringLiteral("cold"),
2698 StringLiteral("convergent"),
2699 StringLiteral("fp-contract"),
2700 StringLiteral("frame-pointer"),
2701 StringLiteral("hot"),
2702 StringLiteral("inlinehint"),
2703 StringLiteral("instrument-function-entry"),
2704 StringLiteral("instrument-function-exit"),
2705 StringLiteral("modular-format"),
2706 StringLiteral("memory"),
2707 StringLiteral("minsize"),
2708 StringLiteral("no_caller_saved_registers"),
2709 StringLiteral("no-signed-zeros-fp-math"),
2710 StringLiteral("no-builtins"),
2711 StringLiteral("nocallback"),
2712 StringLiteral("noduplicate"),
2713 StringLiteral("noinline"),
2714 StringLiteral("noreturn"),
2715 StringLiteral("nounwind"),
2716 StringLiteral("optnone"),
2717 StringLiteral("optsize"),
2718 StringLiteral("returns_twice"),
2719 StringLiteral("save-reg-params"),
2720 StringLiteral("target-features"),
2721 StringLiteral("trap-func-name"),
2722 StringLiteral("tune-cpu"),
2723 StringLiteral("uwtable"),
2724 StringLiteral("vscale_range"),
2725 StringLiteral("willreturn"),
2726 StringLiteral("zero-call-used-regs"),
2727 StringLiteral("denormal_fpenv"),
2728};
2729
2730// List of LLVM IR attributes that are handled by prefix to map onto an MLIR
2731// LLVMFuncOp.
2732static constexpr std::array kExplicitLLVMFuncOpAttributePrefixes{
2733 StringLiteral("no-builtin-"),
2734};
2735
2736template <typename OpTy>
2738 const llvm::AttributeSet &attrs,
2739 OpTy target) {
2740 // 'no-builtins' is the complete collection, and overrides all the rest.
2741 if (attrs.hasAttribute("no-builtins")) {
2742 target.setNobuiltinsAttr(ArrayAttr::get(ctx, {}));
2743 return;
2744 }
2745
2747 for (llvm::Attribute attr : attrs) {
2748 // Attributes that are part of llvm directly (that is, have an AttributeKind
2749 // in the enum) shouldn't be checked.
2750 if (attr.hasKindAsEnum())
2751 continue;
2752
2753 StringRef val = attr.getKindAsString();
2754
2755 if (val.starts_with("no-builtin-"))
2756 nbAttrs.insert(
2757 StringAttr::get(ctx, val.drop_front(sizeof("no-builtin-") - 1)));
2758 }
2759
2760 if (!nbAttrs.empty())
2761 target.setNobuiltinsAttr(ArrayAttr::get(ctx, nbAttrs.getArrayRef()));
2762}
2763
2764template <typename OpTy>
2766 const llvm::AttributeSet &attrs, OpTy target) {
2767 llvm::Attribute attr = attrs.getAttribute(llvm::Attribute::AllocSize);
2768 if (!attr.isValid())
2769 return;
2770
2771 auto [elemSize, numElems] = attr.getAllocSizeArgs();
2772 if (numElems) {
2773 target.setAllocsizeAttr(
2774 DenseI32ArrayAttr::get(ctx, {static_cast<int32_t>(elemSize),
2775 static_cast<int32_t>(*numElems)}));
2776 } else {
2777 target.setAllocsizeAttr(
2778 DenseI32ArrayAttr::get(ctx, {static_cast<int32_t>(elemSize)}));
2779 }
2780}
2781
2782/// Converts LLVM attributes from `func` into MLIR attributes and adds them
2783/// to `funcOp` as passthrough attributes, skipping those listed in
2784/// `kExplicitLLVMFuncAttributes`.
2785static void processPassthroughAttrs(llvm::Function *func, LLVMFuncOp funcOp) {
2786 llvm::AttributeSet funcAttrs = func->getAttributes().getAttributes(
2787 llvm::AttributeList::AttrIndex::FunctionIndex);
2788 ArrayAttr passthroughAttr = convertLLVMAttributesToMLIR(
2789 funcOp.getLoc(), funcOp.getContext(), funcAttrs,
2791 if (!passthroughAttr.empty())
2792 funcOp.setPassthroughAttr(passthroughAttr);
2793}
2794
2796 LLVMFuncOp funcOp) {
2797 processMemoryEffects(func, funcOp);
2798 processDenormalFPEnv(func, funcOp);
2800
2801 if (func->hasFnAttribute(llvm::Attribute::NoInline))
2802 funcOp.setNoInline(true);
2803 if (func->hasFnAttribute(llvm::Attribute::AlwaysInline))
2804 funcOp.setAlwaysInline(true);
2805 if (func->hasFnAttribute(llvm::Attribute::InlineHint))
2806 funcOp.setInlineHint(true);
2807 if (func->hasFnAttribute(llvm::Attribute::OptimizeNone))
2808 funcOp.setOptimizeNone(true);
2809 if (func->hasFnAttribute(llvm::Attribute::Convergent))
2810 funcOp.setConvergent(true);
2811 if (func->hasFnAttribute(llvm::Attribute::NoUnwind))
2812 funcOp.setNoUnwind(true);
2813 if (func->hasFnAttribute(llvm::Attribute::WillReturn))
2814 funcOp.setWillReturn(true);
2815 if (func->hasFnAttribute(llvm::Attribute::NoReturn))
2816 funcOp.setNoreturn(true);
2817 if (func->hasFnAttribute(llvm::Attribute::OptimizeForSize))
2818 funcOp.setOptsize(true);
2819 if (func->hasFnAttribute("save-reg-params"))
2820 funcOp.setSaveRegParams(true);
2821 if (func->hasFnAttribute(llvm::Attribute::MinSize))
2822 funcOp.setMinsize(true);
2823 if (func->hasFnAttribute(llvm::Attribute::ReturnsTwice))
2824 funcOp.setReturnsTwice(true);
2825 if (func->hasFnAttribute(llvm::Attribute::Cold))
2826 funcOp.setCold(true);
2827 if (func->hasFnAttribute(llvm::Attribute::Hot))
2828 funcOp.setHot(true);
2829 if (func->hasFnAttribute(llvm::Attribute::NoDuplicate))
2830 funcOp.setNoduplicate(true);
2831 if (func->hasFnAttribute("no_caller_saved_registers"))
2832 funcOp.setNoCallerSavedRegisters(true);
2833 if (func->hasFnAttribute(llvm::Attribute::NoCallback))
2834 funcOp.setNocallback(true);
2835 if (llvm::Attribute attr = func->getFnAttribute("modular-format");
2836 attr.isStringAttribute())
2837 funcOp.setModularFormat(StringAttr::get(context, attr.getValueAsString()));
2838 if (llvm::Attribute attr = func->getFnAttribute("zero-call-used-regs");
2839 attr.isStringAttribute())
2840 funcOp.setZeroCallUsedRegsAttr(
2841 StringAttr::get(context, attr.getValueAsString()));
2842
2843 if (func->hasFnAttribute("aarch64_pstate_sm_enabled"))
2844 funcOp.setArmStreaming(true);
2845 else if (func->hasFnAttribute("aarch64_pstate_sm_body"))
2846 funcOp.setArmLocallyStreaming(true);
2847 else if (func->hasFnAttribute("aarch64_pstate_sm_compatible"))
2848 funcOp.setArmStreamingCompatible(true);
2849
2850 if (func->hasFnAttribute("aarch64_new_za"))
2851 funcOp.setArmNewZa(true);
2852 else if (func->hasFnAttribute("aarch64_in_za"))
2853 funcOp.setArmInZa(true);
2854 else if (func->hasFnAttribute("aarch64_out_za"))
2855 funcOp.setArmOutZa(true);
2856 else if (func->hasFnAttribute("aarch64_inout_za"))
2857 funcOp.setArmInoutZa(true);
2858 else if (func->hasFnAttribute("aarch64_preserves_za"))
2859 funcOp.setArmPreservesZa(true);
2860
2861 convertNoBuiltinAttrs(context, func->getAttributes().getFnAttrs(), funcOp);
2862 convertAllocsizeAttr(context, func->getAttributes().getFnAttrs(), funcOp);
2863
2864 llvm::Attribute attr = func->getFnAttribute(llvm::Attribute::VScaleRange);
2865 if (attr.isValid()) {
2866 MLIRContext *context = funcOp.getContext();
2867 auto intTy = IntegerType::get(context, 32);
2868 funcOp.setVscaleRangeAttr(LLVM::VScaleRangeAttr::get(
2869 context, IntegerAttr::get(intTy, attr.getVScaleRangeMin()),
2870 IntegerAttr::get(intTy, attr.getVScaleRangeMax().value_or(0))));
2871 }
2872
2873 // Process frame-pointer attribute.
2874 if (func->hasFnAttribute("frame-pointer")) {
2875 StringRef stringRefFramePointerKind =
2876 func->getFnAttribute("frame-pointer").getValueAsString();
2877 funcOp.setFramePointerAttr(LLVM::FramePointerKindAttr::get(
2878 funcOp.getContext(), LLVM::framePointerKind::symbolizeFramePointerKind(
2879 stringRefFramePointerKind)
2880 .value()));
2881 }
2882
2883 if (llvm::Attribute attr = func->getFnAttribute("target-cpu");
2884 attr.isStringAttribute())
2885 funcOp.setTargetCpuAttr(StringAttr::get(context, attr.getValueAsString()));
2886
2887 if (llvm::Attribute attr = func->getFnAttribute("tune-cpu");
2888 attr.isStringAttribute())
2889 funcOp.setTuneCpuAttr(StringAttr::get(context, attr.getValueAsString()));
2890
2891 if (llvm::Attribute attr = func->getFnAttribute("target-features");
2892 attr.isStringAttribute())
2893 funcOp.setTargetFeaturesAttr(
2894 LLVM::TargetFeaturesAttr::get(context, attr.getValueAsString()));
2895
2896 if (llvm::Attribute attr = func->getFnAttribute("reciprocal-estimates");
2897 attr.isStringAttribute())
2898 funcOp.setReciprocalEstimatesAttr(
2899 StringAttr::get(context, attr.getValueAsString()));
2900
2901 if (llvm::Attribute attr = func->getFnAttribute("prefer-vector-width");
2902 attr.isStringAttribute())
2903 funcOp.setPreferVectorWidth(attr.getValueAsString());
2904
2905 if (llvm::Attribute attr = func->getFnAttribute("instrument-function-entry");
2906 attr.isStringAttribute())
2907 funcOp.setInstrumentFunctionEntry(
2908 StringAttr::get(context, attr.getValueAsString()));
2909
2910 if (llvm::Attribute attr = func->getFnAttribute("instrument-function-exit");
2911 attr.isStringAttribute())
2912 funcOp.setInstrumentFunctionExit(
2913 StringAttr::get(context, attr.getValueAsString()));
2914
2915 if (llvm::Attribute attr = func->getFnAttribute("no-signed-zeros-fp-math");
2916 attr.isStringAttribute())
2917 funcOp.setNoSignedZerosFpMath(attr.getValueAsBool());
2918
2919 if (llvm::Attribute attr = func->getFnAttribute("fp-contract");
2920 attr.isStringAttribute())
2921 funcOp.setFpContractAttr(StringAttr::get(context, attr.getValueAsString()));
2922
2923 if (func->hasUWTable()) {
2924 ::llvm::UWTableKind uwtableKind = func->getUWTableKind();
2925 funcOp.setUwtableKindAttr(LLVM::UWTableKindAttr::get(
2926 funcOp.getContext(), convertUWTableKindFromLLVM(uwtableKind)));
2927 }
2928}
2929
2930DictionaryAttr
2931ModuleImport::convertArgOrResultAttrSet(llvm::AttributeSet llvmAttrSet) {
2932 SmallVector<NamedAttribute> paramAttrs;
2933 for (auto [llvmKind, mlirName] : getAttrKindToNameMapping()) {
2934 auto llvmAttr = llvmAttrSet.getAttribute(llvmKind);
2935 // Skip attributes that are not attached.
2936 if (!llvmAttr.isValid())
2937 continue;
2938
2939 // TODO: Import captures(none) as a nocapture unit attribute until the
2940 // LLVM dialect switches to the captures representation.
2941 if (llvmAttr.hasKindAsEnum() &&
2942 llvmAttr.getKindAsEnum() == llvm::Attribute::Captures) {
2943 if (llvm::capturesNothing(llvmAttr.getCaptureInfo()))
2944 paramAttrs.push_back(
2945 builder.getNamedAttr(mlirName, builder.getUnitAttr()));
2946 continue;
2947 }
2948
2949 Attribute mlirAttr;
2950 if (llvmAttr.isTypeAttribute())
2951 mlirAttr = TypeAttr::get(convertType(llvmAttr.getValueAsType()));
2952 else if (llvmAttr.isIntAttribute())
2953 mlirAttr = builder.getI64IntegerAttr(llvmAttr.getValueAsInt());
2954 else if (llvmAttr.isEnumAttribute())
2955 mlirAttr = builder.getUnitAttr();
2956 else if (llvmAttr.isConstantRangeAttribute()) {
2957 const llvm::ConstantRange &value = llvmAttr.getValueAsConstantRange();
2958 mlirAttr = builder.getAttr<LLVM::ConstantRangeAttr>(value.getLower(),
2959 value.getUpper());
2960 } else {
2961 llvm_unreachable("unexpected parameter attribute kind");
2962 }
2963 paramAttrs.push_back(builder.getNamedAttr(mlirName, mlirAttr));
2964 }
2965
2966 return builder.getDictionaryAttr(paramAttrs);
2967}
2968
2969void ModuleImport::convertArgAndResultAttrs(llvm::Function *func,
2970 LLVMFuncOp funcOp) {
2971 auto llvmAttrs = func->getAttributes();
2972 for (size_t i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
2973 llvm::AttributeSet llvmArgAttrs = llvmAttrs.getParamAttrs(i);
2974 funcOp.setArgAttrs(i, convertArgOrResultAttrSet(llvmArgAttrs));
2975 }
2976 // Convert the result attributes and attach them wrapped in an ArrayAttribute
2977 // to the funcOp.
2978 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
2979 if (!llvmResAttr.hasAttributes())
2980 return;
2981 funcOp.setResAttrsAttr(
2982 builder.getArrayAttr({convertArgOrResultAttrSet(llvmResAttr)}));
2983}
2984
2986 llvm::CallBase *call, ArgAndResultAttrsOpInterface attrsOp,
2987 ArrayRef<unsigned> immArgPositions) {
2988 // Compute the set of immediate argument positions.
2989 llvm::SmallDenseSet<unsigned> immArgPositionsSet(immArgPositions.begin(),
2990 immArgPositions.end());
2991 // Convert the argument attributes and filter out immediate arguments.
2992 llvm::AttributeList llvmAttrs = call->getAttributes();
2993 SmallVector<llvm::AttributeSet> llvmArgAttrsSet;
2994 bool anyArgAttrs = false;
2995 for (size_t i = 0, e = call->arg_size(); i < e; ++i) {
2996 // Skip immediate arguments.
2997 if (immArgPositionsSet.contains(i))
2998 continue;
2999 llvmArgAttrsSet.emplace_back(llvmAttrs.getParamAttrs(i));
3000 if (llvmArgAttrsSet.back().hasAttributes())
3001 anyArgAttrs = true;
3002 }
3003 auto getArrayAttr = [&](ArrayRef<DictionaryAttr> dictAttrs) {
3005 for (auto &dict : dictAttrs)
3006 attrs.push_back(dict ? dict : builder.getDictionaryAttr({}));
3007 return builder.getArrayAttr(attrs);
3008 };
3009 if (anyArgAttrs) {
3011 for (auto &llvmArgAttrs : llvmArgAttrsSet)
3012 argAttrs.emplace_back(convertArgOrResultAttrSet(llvmArgAttrs));
3013 attrsOp.setArgAttrsAttr(getArrayAttr(argAttrs));
3014 }
3015
3016 // Convert the result attributes.
3017 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
3018 if (!llvmResAttr.hasAttributes())
3019 return;
3020 DictionaryAttr resAttrs = convertArgOrResultAttrSet(llvmResAttr);
3021 attrsOp.setResAttrsAttr(getArrayAttr({resAttrs}));
3022}
3023
3024template <typename Op>
3025static LogicalResult convertCallBaseAttributes(llvm::CallBase *inst, Op op) {
3026 op.setCConv(convertCConvFromLLVM(inst->getCallingConv()));
3027 return success();
3028}
3029
3030LogicalResult ModuleImport::convertInvokeAttributes(llvm::InvokeInst *inst,
3031 InvokeOp op) {
3032 return convertCallBaseAttributes(inst, op);
3033}
3034
3035LogicalResult ModuleImport::convertCallAttributes(llvm::CallInst *inst,
3036 CallOp op) {
3037 setFastmathFlagsAttr(inst, op.getOperation());
3038 // Query the attributes directly instead of using `inst->getFnAttr(Kind)`, the
3039 // latter does additional lookup to the parent and inherits, changing the
3040 // semantics too early.
3041 llvm::AttributeList callAttrs = inst->getAttributes();
3042
3043 op.setTailCallKind(convertTailCallKindFromLLVM(inst->getTailCallKind()));
3044 op.setConvergent(callAttrs.getFnAttr(llvm::Attribute::Convergent).isValid());
3045 op.setNoUnwind(callAttrs.getFnAttr(llvm::Attribute::NoUnwind).isValid());
3046 op.setWillReturn(callAttrs.getFnAttr(llvm::Attribute::WillReturn).isValid());
3047 op.setNoreturn(callAttrs.getFnAttr(llvm::Attribute::NoReturn).isValid());
3048 op.setOptsize(
3049 callAttrs.getFnAttr(llvm::Attribute::OptimizeForSize).isValid());
3050 op.setSaveRegParams(callAttrs.getFnAttr("save-reg-params").isValid());
3051 op.setBuiltin(callAttrs.getFnAttr(llvm::Attribute::Builtin).isValid());
3052 op.setNobuiltin(callAttrs.getFnAttr(llvm::Attribute::NoBuiltin).isValid());
3053 op.setMinsize(callAttrs.getFnAttr(llvm::Attribute::MinSize).isValid());
3054
3055 op.setReturnsTwice(
3056 callAttrs.getFnAttr(llvm::Attribute::ReturnsTwice).isValid());
3057 op.setHot(callAttrs.getFnAttr(llvm::Attribute::Hot).isValid());
3058 op.setCold(callAttrs.getFnAttr(llvm::Attribute::Cold).isValid());
3059 op.setNoduplicate(
3060 callAttrs.getFnAttr(llvm::Attribute::NoDuplicate).isValid());
3061 op.setNoCallerSavedRegisters(
3062 callAttrs.getFnAttr("no_caller_saved_registers").isValid());
3063 op.setNocallback(callAttrs.getFnAttr(llvm::Attribute::NoCallback).isValid());
3064
3065 if (llvm::Attribute attr = callAttrs.getFnAttr("modular-format");
3066 attr.isStringAttribute())
3067 op.setModularFormat(StringAttr::get(context, attr.getValueAsString()));
3068 if (llvm::Attribute attr = callAttrs.getFnAttr("zero-call-used-regs");
3069 attr.isStringAttribute())
3070 op.setZeroCallUsedRegsAttr(
3071 StringAttr::get(context, attr.getValueAsString()));
3072 if (llvm::Attribute attr = callAttrs.getFnAttr("trap-func-name");
3073 attr.isStringAttribute())
3074 op.setTrapFuncNameAttr(StringAttr::get(context, attr.getValueAsString()));
3075 op.setNoInline(callAttrs.getFnAttr(llvm::Attribute::NoInline).isValid());
3076 op.setAlwaysInline(
3077 callAttrs.getFnAttr(llvm::Attribute::AlwaysInline).isValid());
3078 op.setInlineHint(callAttrs.getFnAttr(llvm::Attribute::InlineHint).isValid());
3079
3080 llvm::MemoryEffects memEffects = inst->getMemoryEffects();
3081 ModRefInfo othermem = convertModRefInfoFromLLVM(
3082 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
3083 ModRefInfo argMem = convertModRefInfoFromLLVM(
3084 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
3085 ModRefInfo inaccessibleMem = convertModRefInfoFromLLVM(
3086 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
3087 ModRefInfo errnoMem = convertModRefInfoFromLLVM(
3088 memEffects.getModRef(llvm::MemoryEffects::Location::ErrnoMem));
3089 ModRefInfo targetMem0 = convertModRefInfoFromLLVM(
3090 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem0));
3091 ModRefInfo targetMem1 = convertModRefInfoFromLLVM(
3092 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem1));
3093 auto memAttr =
3094 MemoryEffectsAttr::get(op.getContext(), othermem, argMem, inaccessibleMem,
3095 errnoMem, targetMem0, targetMem1);
3096 // Only set the attribute when it does not match the default value.
3097 if (!memAttr.isReadWrite())
3098 op.setMemoryEffectsAttr(memAttr);
3099
3100 convertNoBuiltinAttrs(op.getContext(), callAttrs.getFnAttrs(), op);
3101 convertAllocsizeAttr(op.getContext(), callAttrs.getFnAttrs(), op);
3102
3103 return convertCallBaseAttributes(inst, op);
3104}
3105
3106LogicalResult ModuleImport::processFunction(llvm::Function *func) {
3107 clearRegionState();
3108
3109 auto functionType =
3110 dyn_cast<LLVMFunctionType>(convertType(func->getFunctionType()));
3111 if (func->isIntrinsic() &&
3112 iface.isConvertibleIntrinsic(func->getIntrinsicID()))
3113 return success();
3114
3115 bool dsoLocal = func->isDSOLocal();
3116 CConv cconv = convertCConvFromLLVM(func->getCallingConv());
3117
3118 // Insert the function at the end of the module.
3119 OpBuilder::InsertionGuard guard(builder);
3120 builder.setInsertionPointToEnd(mlirModule.getBody());
3121
3122 Location loc = debugImporter->translateFuncLocation(func);
3123 LLVMFuncOp funcOp = LLVMFuncOp::create(
3124 builder, loc, func->getName(), functionType,
3125 convertLinkageFromLLVM(func->getLinkage()), dsoLocal, cconv);
3126
3128
3129 if (FlatSymbolRefAttr personality = getPersonalityAsAttr(func))
3130 funcOp.setPersonalityAttr(personality);
3131 else if (func->hasPersonalityFn())
3132 emitWarning(funcOp.getLoc(), "could not deduce personality, skipping it");
3133
3134 if (func->hasGC())
3135 funcOp.setGarbageCollector(StringRef(func->getGC()));
3136
3137 if (func->hasAtLeastLocalUnnamedAddr())
3138 funcOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(func->getUnnamedAddr()));
3139
3140 if (func->hasSection())
3141 funcOp.setSection(StringRef(func->getSection()));
3142
3143 funcOp.setVisibility_(convertVisibilityFromLLVM(func->getVisibility()));
3144
3145 if (func->hasComdat())
3146 funcOp.setComdatAttr(comdatMapping.lookup(func->getComdat()));
3147
3148 if (llvm::MaybeAlign maybeAlign = func->getAlign())
3149 funcOp.setAlignment(maybeAlign->value());
3150
3151 // Handle Function attributes.
3153
3154 // Convert non-debug metadata by using the dialect interface.
3156 func->getAllMetadata(allMetadata);
3157 for (auto &[kind, node] : allMetadata) {
3158 if (!iface.isConvertibleMetadata(kind))
3159 continue;
3160 if (failed(iface.setMetadataAttrs(builder, kind, node, funcOp, *this))) {
3161 emitWarning(funcOp.getLoc())
3162 << "unhandled function metadata: " << diagMD(node, llvmModule.get())
3163 << " on " << diag(*func);
3164 }
3165 }
3166
3167 if (func->isDeclaration())
3168 return success();
3169
3170 // Collect the set of basic blocks reachable from the function's entry block.
3171 // This step is crucial as LLVM IR can contain unreachable blocks that
3172 // self-dominate. As a result, an operation might utilize a variable it
3173 // defines, which the import does not support. Given that MLIR lacks block
3174 // label support, we can safely remove unreachable blocks, as there are no
3175 // indirect branch instructions that could potentially target these blocks.
3176 llvm::df_iterator_default_set<llvm::BasicBlock *> reachable;
3177 for (llvm::BasicBlock *basicBlock : llvm::depth_first_ext(func, reachable))
3178 (void)basicBlock;
3179
3180 // Eagerly create all reachable blocks.
3181 SmallVector<llvm::BasicBlock *> reachableBasicBlocks;
3182 for (llvm::BasicBlock &basicBlock : *func) {
3183 // Skip unreachable blocks.
3184 if (!reachable.contains(&basicBlock)) {
3185 if (basicBlock.hasAddressTaken())
3186 return emitError(funcOp.getLoc())
3187 << "unreachable block '" << basicBlock.getName()
3188 << "' with address taken";
3189 continue;
3190 }
3191 Region &body = funcOp.getBody();
3192 Block *block = builder.createBlock(&body, body.end());
3193 mapBlock(&basicBlock, block);
3194 reachableBasicBlocks.push_back(&basicBlock);
3195 }
3196
3197 // Add function arguments to the entry block.
3198 for (const auto &it : llvm::enumerate(func->args())) {
3199 BlockArgument blockArg = funcOp.getFunctionBody().addArgument(
3200 functionType.getParamType(it.index()), funcOp.getLoc());
3201 mapValue(&it.value(), blockArg);
3202 }
3203
3204 // Process the blocks in topological order. The ordered traversal ensures
3205 // operands defined in a dominating block have a valid mapping to an MLIR
3206 // value once a block is translated.
3208 getTopologicallySortedBlocks(reachableBasicBlocks);
3209 setConstantInsertionPointToStart(lookupBlock(blocks.front()));
3210 for (llvm::BasicBlock *basicBlock : blocks)
3211 if (failed(processBasicBlock(basicBlock, lookupBlock(basicBlock))))
3212 return failure();
3213
3214 // Process the debug intrinsics that require a delayed conversion after
3215 // everything else was converted.
3216 if (failed(processDebugIntrinsics()))
3217 return failure();
3218
3219 // Process the debug records that require a delayed conversion after
3220 // everything else was converted.
3221 if (failed(processDebugRecords()))
3222 return failure();
3223
3224 return success();
3225}
3226
3227/// Checks if `dbgIntr` is a kill location that holds metadata instead of an SSA
3228/// value.
3229static bool isMetadataKillLocation(llvm::DbgVariableIntrinsic *dbgIntr) {
3230 if (!dbgIntr->isKillLocation())
3231 return false;
3232 llvm::Value *value = dbgIntr->getArgOperand(0);
3233 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
3234 if (!nodeAsVal)
3235 return false;
3236 return !isa<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
3237}
3238
3239/// Ensure that the debug intrinsic is inserted right after the operand
3240/// definition. Otherwise, the operand might not necessarily dominate the
3241/// intrinsic. If the defining operation is a terminator, insert the intrinsic
3242/// into a dominated block.
3244 mlir::OpBuilder &builder, DominanceInfo &domInfo, Value argOperand) {
3245 if (Operation *op = argOperand.getDefiningOp();
3246 op && op->hasTrait<OpTrait::IsTerminator>()) {
3247 // Find a dominated block that can hold the debug intrinsic.
3248 auto dominatedBlocks = domInfo.getNode(op->getBlock())->children();
3249 // If no block is dominated by the terminator, this intrinisc cannot be
3250 // converted.
3251 if (dominatedBlocks.empty())
3252 return failure();
3253 // Set insertion point before the terminator, to avoid inserting something
3254 // before landingpads.
3255 Block *dominatedBlock = (*dominatedBlocks.begin())->getBlock();
3256 builder.setInsertionPoint(dominatedBlock->getTerminator());
3257 } else {
3258 Value insertPt = argOperand;
3259 if (auto blockArg = dyn_cast<BlockArgument>(argOperand)) {
3260 // The value might be coming from a phi node and is now a block argument,
3261 // which means the insertion point is set to the start of the block. If
3262 // this block is a target destination of an invoke, the insertion point
3263 // must happen after the landing pad operation.
3264 Block *insertionBlock = argOperand.getParentBlock();
3265 if (!insertionBlock->empty() &&
3266 isa<LandingpadOp>(insertionBlock->front()))
3267 insertPt = cast<LandingpadOp>(insertionBlock->front()).getRes();
3268 }
3269
3270 builder.setInsertionPointAfterValue(insertPt);
3271 }
3272 return success();
3273}
3274
3275std::tuple<DILocalVariableAttr, DIExpressionAttr, Value>
3276ModuleImport::processDebugOpArgumentsAndInsertionPt(
3277 Location loc,
3278 llvm::function_ref<FailureOr<Value>()> convertArgOperandToValue,
3279 llvm::Value *address,
3280 llvm::PointerUnion<llvm::Value *, llvm::DILocalVariable *> variable,
3281 llvm::DIExpression *expression, DominanceInfo &domInfo) {
3282 // Drop debug intrinsics if the associated debug information cannot be
3283 // translated due to an unsupported construct.
3284 DILocalVariableAttr localVarAttr = matchLocalVariableAttr(variable);
3285 if (!localVarAttr)
3286 return {};
3287 FailureOr<Value> argOperand = convertArgOperandToValue();
3288 if (failed(argOperand)) {
3289 emitError(loc) << "failed to convert a debug operand: " << diag(*address);
3290 return {};
3291 }
3292
3293 if (setDebugIntrinsicBuilderInsertionPoint(builder, domInfo, *argOperand)
3294 .failed())
3295 return {};
3296
3297 return {localVarAttr, debugImporter->translateExpression(expression),
3298 *argOperand};
3299}
3300
3301LogicalResult
3302ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr,
3303 DominanceInfo &domInfo) {
3304 Location loc = translateLoc(dbgIntr->getDebugLoc());
3305 auto emitUnsupportedWarning = [&]() {
3306 if (emitExpensiveWarnings)
3307 emitWarning(loc) << "dropped intrinsic: " << diag(*dbgIntr);
3308 return success();
3309 };
3310
3311 OpBuilder::InsertionGuard guard(builder);
3312 auto convertArgOperandToValue = [&]() {
3313 return convertMetadataValue(dbgIntr->getArgOperand(0));
3314 };
3315
3316 // Drop debug intrinsics with an argument list.
3317 // TODO: Support this case.
3318 if (dbgIntr->hasArgList())
3319 return emitUnsupportedWarning();
3320
3321 // Drop debug intrinsics with kill locations that have metadata nodes as
3322 // location operand, which cannot be converted to poison as the type cannot be
3323 // reconstructed.
3324 // TODO: Support this case.
3325 if (isMetadataKillLocation(dbgIntr))
3326 return emitUnsupportedWarning();
3327
3328 auto [localVariableAttr, locationExprAttr, locVal] =
3329 processDebugOpArgumentsAndInsertionPt(
3330 loc, convertArgOperandToValue, dbgIntr->getArgOperand(0),
3331 dbgIntr->getArgOperand(1), dbgIntr->getExpression(), domInfo);
3332
3333 if (!localVariableAttr)
3334 return emitUnsupportedWarning();
3335
3336 if (!locVal) // Expected if localVariableAttr is present.
3337 return failure();
3338
3339 Operation *op = nullptr;
3340 if (isa<llvm::DbgDeclareInst>(dbgIntr))
3341 op = LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,
3342 locationExprAttr);
3343 else if (isa<llvm::DbgValueInst>(dbgIntr))
3344 op = LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,
3345 locationExprAttr);
3346 else
3347 return emitUnsupportedWarning();
3348
3349 mapNoResultOp(dbgIntr, op);
3350 setNonDebugMetadataAttrs(dbgIntr, op);
3351 return success();
3352}
3353
3354LogicalResult
3355ModuleImport::processDebugRecord(llvm::DbgVariableRecord &dbgRecord,
3356 DominanceInfo &domInfo) {
3357 OpBuilder::InsertionGuard guard(builder);
3358 Location loc = translateLoc(dbgRecord.getDebugLoc());
3359 auto emitUnsupportedWarning = [&]() -> LogicalResult {
3360 if (!emitExpensiveWarnings)
3361 return success();
3362 std::string options;
3363 llvm::raw_string_ostream optionsStream(options);
3364 dbgRecord.print(optionsStream);
3365 emitWarning(loc) << "unhandled debug variable record "
3366 << optionsStream.str();
3367 return success();
3368 };
3369
3370 // Drop debug records with an argument list.
3371 // TODO: Support this case.
3372 if (dbgRecord.hasArgList())
3373 return emitUnsupportedWarning();
3374
3375 // Drop all other debug records with a address operand that cannot be
3376 // converted to an SSA value such as an empty metadata node.
3377 // TODO: Support this case.
3378 if (!dbgRecord.getAddress())
3379 return emitUnsupportedWarning();
3380
3381 auto convertArgOperandToValue = [&]() -> FailureOr<Value> {
3382 llvm::Value *value = dbgRecord.getAddress();
3383
3384 // Return the mapped value if it has been converted before.
3385 auto it = valueMapping.find(value);
3386 if (it != valueMapping.end())
3387 return it->getSecond();
3388
3389 // Convert constants such as immediate values that have no mapping yet.
3390 if (auto *constant = dyn_cast<llvm::Constant>(value))
3391 return convertConstantExpr(constant);
3392 return failure();
3393 };
3394
3395 auto [localVariableAttr, locationExprAttr, locVal] =
3396 processDebugOpArgumentsAndInsertionPt(
3397 loc, convertArgOperandToValue, dbgRecord.getAddress(),
3398 dbgRecord.getVariable(), dbgRecord.getExpression(), domInfo);
3399
3400 if (!localVariableAttr)
3401 return emitUnsupportedWarning();
3402
3403 if (!locVal) // Expected if localVariableAttr is present.
3404 return failure();
3405
3406 if (dbgRecord.isDbgDeclare())
3407 LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,
3408 locationExprAttr);
3409 else if (dbgRecord.isDbgValue())
3410 LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,
3411 locationExprAttr);
3412 else // isDbgAssign
3413 return emitUnsupportedWarning();
3414
3415 return success();
3416}
3417
3418LogicalResult ModuleImport::processDebugIntrinsics() {
3419 DominanceInfo domInfo;
3420 for (llvm::Instruction *inst : debugIntrinsics) {
3421 auto *intrCall = cast<llvm::DbgVariableIntrinsic>(inst);
3422 if (failed(processDebugIntrinsic(intrCall, domInfo)))
3423 return failure();
3424 }
3425 return success();
3426}
3427
3428LogicalResult ModuleImport::processDebugRecords() {
3429 DominanceInfo domInfo;
3430 for (llvm::DbgVariableRecord *dbgRecord : dbgRecords)
3431 if (failed(processDebugRecord(*dbgRecord, domInfo)))
3432 return failure();
3433 dbgRecords.clear();
3434 return success();
3435}
3436
3437LogicalResult ModuleImport::processBasicBlock(llvm::BasicBlock *bb,
3438 Block *block) {
3439 builder.setInsertionPointToStart(block);
3440 for (llvm::Instruction &inst : *bb) {
3441 if (failed(processInstruction(&inst)))
3442 return failure();
3443
3444 // Skip additional processing when the instructions is a debug intrinsics
3445 // that was not yet converted.
3446 if (debugIntrinsics.contains(&inst))
3447 continue;
3448
3449 // Set the non-debug metadata attributes on the imported operation and emit
3450 // a warning if an instruction other than a phi instruction is dropped
3451 // during the import.
3452 if (Operation *op = lookupOperation(&inst)) {
3453 setNonDebugMetadataAttrs(&inst, op);
3454 } else if (inst.getOpcode() != llvm::Instruction::PHI) {
3455 if (emitExpensiveWarnings) {
3456 Location loc = debugImporter->translateLoc(inst.getDebugLoc());
3457 emitWarning(loc) << "dropped instruction: " << diag(inst);
3458 }
3459 }
3460 }
3461
3462 if (bb->hasAddressTaken()) {
3463 OpBuilder::InsertionGuard guard(builder);
3464 builder.setInsertionPointToStart(block);
3465 BlockTagOp::create(builder, block->getParentOp()->getLoc(),
3466 BlockTagAttr::get(context, bb->getNumber()));
3467 }
3468 return success();
3469}
3470
3471FailureOr<SmallVector<AccessGroupAttr>>
3472ModuleImport::lookupAccessGroupAttrs(const llvm::MDNode *node) const {
3473 return loopAnnotationImporter->lookupAccessGroupAttrs(node);
3474}
3475
3476LoopAnnotationAttr
3478 Location loc) const {
3479 return loopAnnotationImporter->translateLoopAnnotation(node, loc);
3480}
3481
3482FailureOr<DereferenceableAttr>
3484 unsigned kindID) {
3485 Location loc = mlirModule.getLoc();
3486
3487 // The only operand should be a constant integer representing the number of
3488 // dereferenceable bytes.
3489 if (node->getNumOperands() != 1)
3490 return emitError(loc) << "dereferenceable metadata must have one operand: "
3491 << diagMD(node, llvmModule.get());
3492
3493 auto *numBytesMD = dyn_cast<llvm::ConstantAsMetadata>(node->getOperand(0));
3494 auto *numBytesCst = dyn_cast<llvm::ConstantInt>(numBytesMD->getValue());
3495 if (!numBytesCst || !numBytesCst->getValue().isNonNegative())
3496 return emitError(loc) << "dereferenceable metadata operand must be a "
3497 "non-negative constant integer: "
3498 << diagMD(node, llvmModule.get());
3499
3500 bool mayBeNull = kindID == llvm::LLVMContext::MD_dereferenceable_or_null;
3501 auto derefAttr = builder.getAttr<DereferenceableAttr>(
3502 numBytesCst->getZExtValue(), mayBeNull);
3503
3504 return derefAttr;
3505}
3506
3508 std::unique_ptr<llvm::Module> llvmModule, MLIRContext *context,
3509 bool emitExpensiveWarnings, bool dropDICompositeTypeElements,
3510 bool loadAllDialects, bool preferUnregisteredIntrinsics,
3511 bool importStructsAsLiterals) {
3512 // Preload all registered dialects to allow the import to iterate the
3513 // registered LLVMImportDialectInterface implementations and query the
3514 // supported LLVM IR constructs before starting the translation. Assumes the
3515 // LLVM and DLTI dialects that convert the core LLVM IR constructs have been
3516 // registered before.
3517 assert(llvm::is_contained(context->getAvailableDialects(),
3518 LLVMDialect::getDialectNamespace()));
3519 assert(llvm::is_contained(context->getAvailableDialects(),
3520 DLTIDialect::getDialectNamespace()));
3521 if (loadAllDialects)
3522 context->loadAllAvailableDialects();
3523 OwningOpRef<ModuleOp> module(ModuleOp::create(FileLineColLoc::get(
3524 StringAttr::get(context, llvmModule->getSourceFileName()), /*line=*/0,
3525 /*column=*/0)));
3526
3527 ModuleImport moduleImport(module.get(), std::move(llvmModule),
3528 emitExpensiveWarnings, dropDICompositeTypeElements,
3529 preferUnregisteredIntrinsics,
3530 importStructsAsLiterals);
3531 if (failed(moduleImport.initializeImportInterface()))
3532 return {};
3533 if (failed(moduleImport.convertDataLayout()))
3534 return {};
3535 if (failed(moduleImport.convertComdats()))
3536 return {};
3537 if (failed(moduleImport.convertMetadata()))
3538 return {};
3539 if (failed(moduleImport.convertGlobals()))
3540 return {};
3541 if (failed(moduleImport.convertFunctions()))
3542 return {};
3543 if (failed(moduleImport.convertAliases()))
3544 return {};
3545 if (failed(moduleImport.convertIFuncs()))
3546 return {};
3547 moduleImport.convertTargetTriple();
3548 moduleImport.convertModuleLevelAsm();
3549 return module;
3550}
return success()
ArrayAttr()
b getContext())
*if copies could not be generated due to yet unimplemented cases *copyInPlacementStart and copyOutPlacementStart in copyPlacementBlock *specify the insertion points where the incoming copies and outgoing should be inserted(the insertion happens right before the *insertion point). Since `begin` can itself be invalidated due to the memref *rewriting done from this method
static ArrayAttr convertLLVMAttributesToMLIR(Location loc, MLIRContext *context, llvm::AttributeSet attributes, ArrayRef< StringLiteral > attributesToSkip={}, ArrayRef< StringLiteral > attributePrefixesToSkip={})
Converts LLVM string, integer, and enum attributes into MLIR attributes, skipping those in attributes...
static StringRef getLLVMSyncScope(llvm::Instruction *inst)
Converts the sync scope identifier of inst to the string representation necessary to build an atomic ...
static std::string diag(const llvm::Value &value)
static void processPassthroughAttrs(llvm::Function *func, LLVMFuncOp funcOp)
Converts LLVM attributes from func into MLIR attributes and adds them to funcOp as passthrough attrib...
static SmallVector< Attribute > getSequenceConstantAsAttrs(OpBuilder &builder, llvm::ConstantDataSequential *constSequence)
Returns an integer or float attribute array for the provided constant sequence constSequence or nullp...
static LogicalResult convertCallBaseAttributes(llvm::CallBase *inst, Op op)
static void processMemoryEffects(llvm::Function *func, LLVMFuncOp funcOp)
static Attribute convertCGProfileModuleFlagValue(ModuleOp mlirModule, llvm::MDTuple *mdTuple)
static constexpr std::array kExplicitLLVMFuncOpAttributePrefixes
static constexpr StringRef getGlobalDtorsVarName()
Returns the name of the global_dtors global variables.
static Type getVectorTypeForAttr(Type type, ArrayRef< int64_t > arrayShape={})
Returns type if it is a builtin integer or floating-point vector type that can be used to create an a...
static LogicalResult convertInstructionImpl(OpBuilder &odsBuilder, llvm::Instruction *inst, ModuleImport &moduleImport, LLVMImportInterface &iface)
Converts the LLVM instructions that have a generated MLIR builder.
static constexpr StringRef getNamelessGlobalPrefix()
Prefix used for symbols of nameless llvm globals.
static Attribute convertModuleFlagValueFromMDTuple(ModuleOp mlirModule, const llvm::Module *llvmModule, StringRef key, llvm::MDTuple *mdTuple)
Invoke specific handlers for each known module flag value, returns nullptr if the key is unknown or u...
static constexpr std::array kExplicitLLVMFuncOpAttributes
static constexpr StringRef getGlobalComdatOpName()
Returns the symbol name for the module-level comdat operation.
static void convertNoBuiltinAttrs(MLIRContext *ctx, const llvm::AttributeSet &attrs, OpTy target)
static SmallVector< int64_t > getPositionFromIndices(ArrayRef< unsigned > indices)
Converts an array of unsigned indices to a signed integer position array.
static LogicalResult setDebugIntrinsicBuilderInsertionPoint(mlir::OpBuilder &builder, DominanceInfo &domInfo, Value argOperand)
Ensure that the debug intrinsic is inserted right after the operand definition.
static LogicalResult checkFunctionTypeCompatibility(LLVMFunctionType callType, LLVMFunctionType calleeType)
Checks if callType and calleeType are compatible and can be represented in MLIR.
static void processDenormalFPEnv(llvm::Function *func, LLVMFuncOp funcOp)
static std::optional< ProfileSummaryFormatKind > convertProfileSummaryFormat(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &formatMD)
static constexpr StringRef getGlobalCtorsVarName()
Returns the name of the global_ctors global variables.
static FailureOr< uint64_t > convertInt64FromKeyValueTuple(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &md, StringRef matchKey)
Extract an integer value from a two element tuple (<key, value>).
static void processTargetSpecificAttrs(llvm::GlobalVariable *globalVar, GlobalOp globalOp)
Converts LLVM attributes from globalVar into MLIR attributes and adds them to globalOp as target-spec...
static Attribute convertProfileSummaryModuleFlagValue(ModuleOp mlirModule, const llvm::Module *llvmModule, llvm::MDTuple *mdTuple)
static llvm::MDTuple * getTwoElementMDTuple(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &md)
Extract a two element MDTuple from a MDOperand.
static bool isMetadataKillLocation(llvm::DbgVariableIntrinsic *dbgIntr)
Checks if dbgIntr is a kill location that holds metadata instead of an SSA value.
static TypedAttr getScalarConstantAsAttr(OpBuilder &builder, llvm::Constant *constScalar)
Returns an integer or float attribute for the provided scalar constant constScalar or nullptr if the ...
static void convertAllocsizeAttr(MLIRContext *ctx, const llvm::AttributeSet &attrs, OpTy target)
static std::string diagMD(const llvm::Metadata *node, const llvm::Module *module)
static llvm::ConstantAsMetadata * getConstantMDFromKeyValueTuple(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &md, StringRef matchKey, bool optional=false)
Extract a constant metadata value from a two element tuple (<key, value>).
static FailureOr< SmallVector< ModuleFlagProfileSummaryDetailedAttr > > convertProfileSummaryDetailed(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &summaryMD)
static SetVector< llvm::BasicBlock * > getTopologicallySortedBlocks(ArrayRef< llvm::BasicBlock * > basicBlocks)
Get a topologically sorted list of blocks for the given basic blocks.
static llvm::ManagedStatic< PassManagerOptions > options
Attributes are known-constant values of operations.
Definition Attributes.h:25
This class represents an argument of a Block.
Definition Value.h:306
Block represents an ordered list of Operations.
Definition Block.h:33
bool empty()
Definition Block.h:158
Operation & front()
Definition Block.h:163
Operation * getTerminator()
Get the terminator operation of this block.
Definition Block.cpp:249
Operation * getParentOp()
Returns the closest surrounding operation that contains this block.
Definition Block.cpp:31
UnitAttr getUnitAttr()
Definition Builders.cpp:102
IntegerAttr getIntegerAttr(Type type, int64_t value)
Definition Builders.cpp:232
FloatAttr getFloatAttr(Type type, double value)
Definition Builders.cpp:258
IntegerAttr getI64IntegerAttr(int64_t value)
Definition Builders.cpp:116
MLIRContext * getContext() const
Definition Builders.h:56
NamedAttribute getNamedAttr(StringRef name, Attribute val)
Definition Builders.cpp:98
Attr getAttr(Args &&...args)
Get or construct an instance of the attribute Attr with provided arguments.
Definition Builders.h:100
static DenseElementsAttr get(ShapedType type, ArrayRef< Attribute > values)
Constructs a dense elements attribute from an array of element values.
static DistinctAttr create(Attribute referencedAttr)
Creates a distinct attribute that associates a referenced attribute with a unique identifier.
A class for computing basic dominance information.
Definition Dominance.h: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:350
This class helps build Operations.
Definition Builders.h:209
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
Definition Builders.h:400
void setInsertionPointToEnd(Block *block)
Sets the insertion point to the end of the specified block.
Definition Builders.h:438
void setInsertionPointAfterValue(Value val)
Sets the insertion point to the node after the specified value.
Definition Builders.h:423
This class provides the API for ops that are known to be terminators.
This provides public APIs that all operations should have.
Operation is the basic unit of execution within MLIR.
Definition Operation.h:88
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
Definition Operation.h:778
Location getLoc()
The source location the operation was defined or derived from.
Definition Operation.h:244
This class acts as an owning reference to an op, and will automatically destroy the held op on destru...
Definition OwningOpRef.h:29
OpTy get() const
Allow accessing the internal op.
Definition OwningOpRef.h:51
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition Region.h:26
iterator end()
Definition Region.h:56
static SmallString< N > generateSymbolName(StringRef name, UniqueChecker uniqueChecker, unsigned &uniquingCounter)
Generate a unique symbol name.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
MLIRContext * getContext() const
Return the MLIRContext in which this type was uniqued.
Definition Types.cpp:35
bool isIntOrFloat() const
Return true if this is an integer (of any signedness) or a float type.
Definition Types.cpp:118
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
Block * getParentBlock()
Return the Block in which this Value is defined.
Definition Value.cpp:46
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
Definition Value.cpp:18
static DenseArrayAttrImpl get(MLIRContext *context, ArrayRef< int32_t > content)
DominanceInfoNode * getNode(Block *a)
Return the dominance node from the Region containing block A.
Definition Dominance.h: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:717
Include the generated interface declarations.
bool matchPattern(Value value, const Pattern &pattern)
Entry point for matching a pattern over a Value.
Definition Matchers.h:490
InFlightDiagnostic emitWarning(Location loc)
Utility method to emit a warning message using this location.
llvm::DenseSet< ValueT, ValueInfoT > DenseSet
Definition LLVM.h:120
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
llvm::SetVector< T, Vector, Set, N > SetVector
Definition LLVM.h:123
llvm::DenseMap< KeyT, ValueT, KeyInfoT, BucketT > DenseMap
Definition LLVM.h:118
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.