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 (inst->getOpcode() == llvm::Instruction::Br) {
2258 auto *brInst = cast<llvm::BranchInst>(inst);
2259
2260 SmallVector<Block *> succBlocks;
2261 SmallVector<SmallVector<Value>> succBlockArgs;
2262 for (auto i : llvm::seq<unsigned>(0, brInst->getNumSuccessors())) {
2263 llvm::BasicBlock *succ = brInst->getSuccessor(i);
2264 SmallVector<Value> blockArgs;
2265 if (failed(convertBranchArgs(brInst, succ, blockArgs)))
2266 return failure();
2267 succBlocks.push_back(lookupBlock(succ));
2268 succBlockArgs.push_back(blockArgs);
2269 }
2270
2271 if (!brInst->isConditional()) {
2272 auto brOp = LLVM::BrOp::create(builder, loc, succBlockArgs.front(),
2273 succBlocks.front());
2274 mapNoResultOp(inst, brOp);
2275 return success();
2276 }
2277 FailureOr<Value> condition = convertValue(brInst->getCondition());
2278 if (failed(condition))
2279 return failure();
2280 auto condBrOp = LLVM::CondBrOp::create(
2281 builder, loc, *condition, succBlocks.front(), succBlockArgs.front(),
2282 succBlocks.back(), succBlockArgs.back());
2283 mapNoResultOp(inst, condBrOp);
2284 return success();
2285 }
2286 if (inst->getOpcode() == llvm::Instruction::Switch) {
2287 auto *swInst = cast<llvm::SwitchInst>(inst);
2288 // Process the condition value.
2289 FailureOr<Value> condition = convertValue(swInst->getCondition());
2290 if (failed(condition))
2291 return failure();
2292 SmallVector<Value> defaultBlockArgs;
2293 // Process the default case.
2294 llvm::BasicBlock *defaultBB = swInst->getDefaultDest();
2295 if (failed(convertBranchArgs(swInst, defaultBB, defaultBlockArgs)))
2296 return failure();
2297
2298 // Process the cases.
2299 unsigned numCases = swInst->getNumCases();
2300 SmallVector<SmallVector<Value>> caseOperands(numCases);
2301 SmallVector<ValueRange> caseOperandRefs(numCases);
2302 SmallVector<APInt> caseValues(numCases);
2303 SmallVector<Block *> caseBlocks(numCases);
2304 for (const auto &it : llvm::enumerate(swInst->cases())) {
2305 const llvm::SwitchInst::CaseHandle &caseHandle = it.value();
2306 llvm::BasicBlock *succBB = caseHandle.getCaseSuccessor();
2307 if (failed(convertBranchArgs(swInst, succBB, caseOperands[it.index()])))
2308 return failure();
2309 caseOperandRefs[it.index()] = caseOperands[it.index()];
2310 caseValues[it.index()] = caseHandle.getCaseValue()->getValue();
2311 caseBlocks[it.index()] = lookupBlock(succBB);
2312 }
2313
2314 auto switchOp = SwitchOp::create(builder, loc, *condition,
2315 lookupBlock(defaultBB), defaultBlockArgs,
2316 caseValues, caseBlocks, caseOperandRefs);
2317 mapNoResultOp(inst, switchOp);
2318 return success();
2319 }
2320 if (inst->getOpcode() == llvm::Instruction::PHI) {
2321 Type type = convertType(inst->getType());
2322 mapValue(inst, builder.getInsertionBlock()->addArgument(
2323 type, translateLoc(inst->getDebugLoc())));
2324 return success();
2325 }
2326 if (inst->getOpcode() == llvm::Instruction::Call) {
2327 auto *callInst = cast<llvm::CallInst>(inst);
2328 llvm::Value *calledOperand = callInst->getCalledOperand();
2329
2330 FailureOr<SmallVector<Value>> operands =
2331 convertCallOperands(callInst, /*allowInlineAsm=*/true);
2332 if (failed(operands))
2333 return failure();
2334
2335 auto callOp = [&]() -> FailureOr<Operation *> {
2336 if (auto *asmI = dyn_cast<llvm::InlineAsm>(calledOperand)) {
2337 Type resultTy = convertType(callInst->getType());
2338 if (!resultTy)
2339 return failure();
2340 ArrayAttr operandAttrs = convertAsmInlineOperandAttrs(*callInst);
2341 return InlineAsmOp::create(
2342 builder, loc, resultTy, *operands,
2343 builder.getStringAttr(asmI->getAsmString()),
2344 builder.getStringAttr(asmI->getConstraintString()),
2345 asmI->hasSideEffects(), asmI->isAlignStack(),
2346 convertTailCallKindFromLLVM(callInst->getTailCallKind()),
2347 AsmDialectAttr::get(
2348 mlirModule.getContext(),
2349 convertAsmDialectFromLLVM(asmI->getDialect())),
2350 operandAttrs)
2351 .getOperation();
2352 }
2353 bool isIncompatibleCall;
2354 FailureOr<LLVMFunctionType> funcTy =
2355 convertFunctionType(callInst, isIncompatibleCall);
2356 if (failed(funcTy))
2357 return failure();
2358
2359 FlatSymbolRefAttr callee = nullptr;
2360 if (isIncompatibleCall) {
2361 // Use an indirect call (in order to represent valid and verifiable LLVM
2362 // IR). Build the indirect call by passing an empty `callee` operand and
2363 // insert into `operands` to include the indirect call target.
2364 FlatSymbolRefAttr calleeSym = convertCalleeName(callInst);
2365 Value indirectCallVal = LLVM::AddressOfOp::create(
2366 builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);
2367 operands->insert(operands->begin(), indirectCallVal);
2368 } else {
2369 // Regular direct call using callee name.
2370 callee = convertCalleeName(callInst);
2371 }
2372 CallOp callOp = CallOp::create(builder, loc, *funcTy, callee, *operands);
2373
2374 if (failed(convertCallAttributes(callInst, callOp)))
2375 return failure();
2376
2377 // Handle parameter and result attributes unless it's an incompatible
2378 // call.
2379 if (!isIncompatibleCall)
2380 convertArgAndResultAttrs(callInst, callOp);
2381 return callOp.getOperation();
2382 }();
2383
2384 if (failed(callOp))
2385 return failure();
2386
2387 if (!callInst->getType()->isVoidTy())
2388 mapValue(inst, (*callOp)->getResult(0));
2389 else
2390 mapNoResultOp(inst, *callOp);
2391 return success();
2392 }
2393 if (inst->getOpcode() == llvm::Instruction::LandingPad) {
2394 auto *lpInst = cast<llvm::LandingPadInst>(inst);
2395
2396 SmallVector<Value> operands;
2397 operands.reserve(lpInst->getNumClauses());
2398 for (auto i : llvm::seq<unsigned>(0, lpInst->getNumClauses())) {
2399 FailureOr<Value> operand = convertValue(lpInst->getClause(i));
2400 if (failed(operand))
2401 return failure();
2402 operands.push_back(*operand);
2403 }
2404
2405 Type type = convertType(lpInst->getType());
2406 auto lpOp =
2407 LandingpadOp::create(builder, loc, type, lpInst->isCleanup(), operands);
2408 mapValue(inst, lpOp);
2409 return success();
2410 }
2411 if (inst->getOpcode() == llvm::Instruction::Invoke) {
2412 auto *invokeInst = cast<llvm::InvokeInst>(inst);
2413
2414 if (invokeInst->isInlineAsm())
2415 return emitError(loc) << "invoke of inline assembly is not supported";
2416
2417 FailureOr<SmallVector<Value>> operands = convertCallOperands(invokeInst);
2418 if (failed(operands))
2419 return failure();
2420
2421 // Check whether the invoke result is an argument to the normal destination
2422 // block.
2423 bool invokeResultUsedInPhi = llvm::any_of(
2424 invokeInst->getNormalDest()->phis(), [&](const llvm::PHINode &phi) {
2425 return phi.getIncomingValueForBlock(invokeInst->getParent()) ==
2426 invokeInst;
2427 });
2428
2429 Block *normalDest = lookupBlock(invokeInst->getNormalDest());
2430 Block *directNormalDest = normalDest;
2431 if (invokeResultUsedInPhi) {
2432 // The invoke result cannot be an argument to the normal destination
2433 // block, as that would imply using the invoke operation result in its
2434 // definition, so we need to create a dummy block to serve as an
2435 // intermediate destination.
2436 OpBuilder::InsertionGuard g(builder);
2437 directNormalDest = builder.createBlock(normalDest);
2438 }
2439
2440 SmallVector<Value> unwindArgs;
2441 if (failed(convertBranchArgs(invokeInst, invokeInst->getUnwindDest(),
2442 unwindArgs)))
2443 return failure();
2444
2445 bool isIncompatibleInvoke;
2446 FailureOr<LLVMFunctionType> funcTy =
2447 convertFunctionType(invokeInst, isIncompatibleInvoke);
2448 if (failed(funcTy))
2449 return failure();
2450
2451 FlatSymbolRefAttr calleeName = nullptr;
2452 if (isIncompatibleInvoke) {
2453 // Use an indirect invoke (in order to represent valid and verifiable LLVM
2454 // IR). Build the indirect invoke by passing an empty `callee` operand and
2455 // insert into `operands` to include the indirect invoke target.
2456 FlatSymbolRefAttr calleeSym = convertCalleeName(invokeInst);
2457 Value indirectInvokeVal = LLVM::AddressOfOp::create(
2458 builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);
2459 operands->insert(operands->begin(), indirectInvokeVal);
2460 } else {
2461 // Regular direct invoke using callee name.
2462 calleeName = convertCalleeName(invokeInst);
2463 }
2464 // Create the invoke operation. Normal destination block arguments will be
2465 // added later on to handle the case in which the operation result is
2466 // included in this list.
2467 auto invokeOp = InvokeOp::create(
2468 builder, loc, *funcTy, calleeName, *operands, directNormalDest,
2469 ValueRange(), lookupBlock(invokeInst->getUnwindDest()), unwindArgs);
2470
2471 if (failed(convertInvokeAttributes(invokeInst, invokeOp)))
2472 return failure();
2473
2474 // Handle parameter and result attributes unless it's an incompatible
2475 // invoke.
2476 if (!isIncompatibleInvoke)
2477 convertArgAndResultAttrs(invokeInst, invokeOp);
2478
2479 if (!invokeInst->getType()->isVoidTy())
2480 mapValue(inst, invokeOp.getResults().front());
2481 else
2482 mapNoResultOp(inst, invokeOp);
2483
2484 SmallVector<Value> normalArgs;
2485 if (failed(convertBranchArgs(invokeInst, invokeInst->getNormalDest(),
2486 normalArgs)))
2487 return failure();
2488
2489 if (invokeResultUsedInPhi) {
2490 // The dummy normal dest block will just host an unconditional branch
2491 // instruction to the normal destination block passing the required block
2492 // arguments (including the invoke operation's result).
2493 OpBuilder::InsertionGuard g(builder);
2494 builder.setInsertionPointToStart(directNormalDest);
2495 LLVM::BrOp::create(builder, loc, normalArgs, normalDest);
2496 } else {
2497 // If the invoke operation's result is not a block argument to the normal
2498 // destination block, just add the block arguments as usual.
2499 assert(llvm::none_of(
2500 normalArgs,
2501 [&](Value val) { return val.getDefiningOp() == invokeOp; }) &&
2502 "An llvm.invoke operation cannot pass its result as a block "
2503 "argument.");
2504 invokeOp.getNormalDestOperandsMutable().append(normalArgs);
2505 }
2506
2507 return success();
2508 }
2509 if (inst->getOpcode() == llvm::Instruction::GetElementPtr) {
2510 auto *gepInst = cast<llvm::GetElementPtrInst>(inst);
2511 Type sourceElementType = convertType(gepInst->getSourceElementType());
2512 FailureOr<Value> basePtr = convertValue(gepInst->getOperand(0));
2513 if (failed(basePtr))
2514 return failure();
2515
2516 // Treat every indices as dynamic since GEPOp::build will refine those
2517 // indices into static attributes later. One small downside of this
2518 // approach is that many unused `llvm.mlir.constant` would be emitted
2519 // at first place.
2520 SmallVector<GEPArg> indices;
2521 for (llvm::Value *operand : llvm::drop_begin(gepInst->operand_values())) {
2522 FailureOr<Value> index = convertValue(operand);
2523 if (failed(index))
2524 return failure();
2525 indices.push_back(*index);
2526 }
2527
2528 Type type = convertType(inst->getType());
2529 auto gepOp = GEPOp::create(
2530 builder, loc, type, sourceElementType, *basePtr, indices,
2531 static_cast<GEPNoWrapFlags>(gepInst->getNoWrapFlags().getRaw()));
2532 mapValue(inst, gepOp);
2533 return success();
2534 }
2535
2536 if (inst->getOpcode() == llvm::Instruction::IndirectBr) {
2537 auto *indBrInst = cast<llvm::IndirectBrInst>(inst);
2538
2539 FailureOr<Value> basePtr = convertValue(indBrInst->getAddress());
2540 if (failed(basePtr))
2541 return failure();
2542
2543 SmallVector<Block *> succBlocks;
2544 SmallVector<SmallVector<Value>> succBlockArgs;
2545 for (auto i : llvm::seq<unsigned>(0, indBrInst->getNumSuccessors())) {
2546 llvm::BasicBlock *succ = indBrInst->getSuccessor(i);
2547 SmallVector<Value> blockArgs;
2548 if (failed(convertBranchArgs(indBrInst, succ, blockArgs)))
2549 return failure();
2550 succBlocks.push_back(lookupBlock(succ));
2551 succBlockArgs.push_back(blockArgs);
2552 }
2553 SmallVector<ValueRange> succBlockArgsRange =
2554 llvm::to_vector_of<ValueRange>(succBlockArgs);
2555 Location loc = translateLoc(inst->getDebugLoc());
2556 auto indBrOp = LLVM::IndirectBrOp::create(builder, loc, *basePtr,
2557 succBlockArgsRange, succBlocks);
2558
2559 mapNoResultOp(inst, indBrOp);
2560 return success();
2561 }
2562
2563 // Convert all instructions that have an mlirBuilder.
2564 if (succeeded(convertInstructionImpl(builder, inst, *this, iface)))
2565 return success();
2566
2567 return emitError(loc) << "unhandled instruction: " << diag(*inst);
2568}
2569
2570LogicalResult ModuleImport::processInstruction(llvm::Instruction *inst) {
2571 // FIXME: Support uses of SubtargetData.
2572 // FIXME: Add support for call / operand attributes.
2573 // FIXME: Add support for the cleanupret, catchret, catchswitch, callbr,
2574 // vaarg, catchpad, cleanuppad instructions.
2575
2576 // Convert LLVM intrinsics calls to MLIR intrinsics.
2577 if (auto *intrinsic = dyn_cast<llvm::IntrinsicInst>(inst))
2578 return convertIntrinsic(intrinsic);
2579
2580 // Process debug records attached to this instruction. Debug variable records
2581 // are stored for later processing after all SSA values are converted, while
2582 // debug label records can be converted immediately.
2583 if (inst->DebugMarker) {
2584 for (llvm::DbgRecord &dbgRecord : inst->DebugMarker->getDbgRecordRange()) {
2585 // Store debug variable records for later processing.
2586 if (auto *dbgVariableRecord =
2587 dyn_cast<llvm::DbgVariableRecord>(&dbgRecord)) {
2588 addDebugRecord(dbgVariableRecord);
2589 continue;
2590 }
2591 Location loc = translateLoc(dbgRecord.getDebugLoc());
2592 auto emitUnsupportedWarning = [&]() -> LogicalResult {
2593 if (!emitExpensiveWarnings)
2594 return success();
2595 std::string options;
2596 llvm::raw_string_ostream optionsStream(options);
2597 dbgRecord.print(optionsStream);
2598 emitWarning(loc) << "unhandled debug record " << optionsStream.str();
2599 return success();
2600 };
2601 // Convert the debug label records in-place.
2602 if (auto *dbgLabelRecord = dyn_cast<llvm::DbgLabelRecord>(&dbgRecord)) {
2603 DILabelAttr labelAttr =
2604 debugImporter->translate(dbgLabelRecord->getLabel());
2605 if (!labelAttr)
2606 return emitUnsupportedWarning();
2607 LLVM::DbgLabelOp::create(builder, loc, labelAttr);
2608 continue;
2609 }
2610 // Warn if an unsupported debug record is encountered.
2611 return emitUnsupportedWarning();
2612 }
2613 }
2614
2615 // Convert all remaining LLVM instructions to MLIR operations.
2616 return convertInstruction(inst);
2617}
2618
2619FlatSymbolRefAttr ModuleImport::getPersonalityAsAttr(llvm::Function *f) {
2620 if (!f->hasPersonalityFn())
2621 return nullptr;
2622
2623 llvm::Constant *pf = f->getPersonalityFn();
2624
2625 // If it directly has a name, we can use it.
2626 if (pf->hasName())
2627 return SymbolRefAttr::get(builder.getContext(), pf->getName());
2628
2629 // If it doesn't have a name, currently, only function pointers that are
2630 // bitcast to i8* are parsed.
2631 if (auto *ce = dyn_cast<llvm::ConstantExpr>(pf)) {
2632 if (ce->getOpcode() == llvm::Instruction::BitCast &&
2633 ce->getType() == llvm::PointerType::getUnqual(f->getContext())) {
2634 if (auto *func = dyn_cast<llvm::Function>(ce->getOperand(0)))
2635 return SymbolRefAttr::get(builder.getContext(), func->getName());
2636 }
2637 }
2638 return FlatSymbolRefAttr();
2639}
2640
2641static void processMemoryEffects(llvm::Function *func, LLVMFuncOp funcOp) {
2642 llvm::MemoryEffects memEffects = func->getMemoryEffects();
2643
2644 auto othermem = convertModRefInfoFromLLVM(
2645 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
2646 auto argMem = convertModRefInfoFromLLVM(
2647 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
2648 auto inaccessibleMem = convertModRefInfoFromLLVM(
2649 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
2650 auto errnoMem = convertModRefInfoFromLLVM(
2651 memEffects.getModRef(llvm::MemoryEffects::Location::ErrnoMem));
2652 auto targetMem0 = convertModRefInfoFromLLVM(
2653 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem0));
2654 auto targetMem1 = convertModRefInfoFromLLVM(
2655 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem1));
2656 auto memAttr =
2657 MemoryEffectsAttr::get(funcOp.getContext(), othermem, argMem,
2658 inaccessibleMem, errnoMem, targetMem0, targetMem1);
2659 // Only set the attr when it does not match the default value.
2660 if (memAttr.isReadWrite())
2661 return;
2662 funcOp.setMemoryEffectsAttr(memAttr);
2663}
2664
2665static void processDenormalFPEnv(llvm::Function *func, LLVMFuncOp funcOp) {
2666 llvm::DenormalFPEnv denormalFpEnv = func->getDenormalFPEnv();
2667 // Only set the attr when it does not match the default value.
2668 if (denormalFpEnv == llvm::DenormalFPEnv::getDefault())
2669 return;
2670
2671 llvm::DenormalMode defaultMode = denormalFpEnv.DefaultMode;
2672 llvm::DenormalMode floatMode = denormalFpEnv.F32Mode;
2673
2674 auto denormalFpEnvAttr = DenormalFPEnvAttr::get(
2675 funcOp.getContext(), convertDenormalModeKindFromLLVM(defaultMode.Output),
2676 convertDenormalModeKindFromLLVM(defaultMode.Input),
2677 convertDenormalModeKindFromLLVM(floatMode.Output),
2678 convertDenormalModeKindFromLLVM(floatMode.Input));
2679 funcOp.setDenormalFpenvAttr(denormalFpEnvAttr);
2680}
2681
2682// List of LLVM IR attributes that map to an explicit attribute on the MLIR
2683// LLVMFuncOp.
2684static constexpr std::array kExplicitLLVMFuncOpAttributes{
2685 StringLiteral("aarch64_in_za"),
2686 StringLiteral("aarch64_inout_za"),
2687 StringLiteral("aarch64_new_za"),
2688 StringLiteral("aarch64_out_za"),
2689 StringLiteral("aarch64_preserves_za"),
2690 StringLiteral("aarch64_pstate_sm_body"),
2691 StringLiteral("aarch64_pstate_sm_compatible"),
2692 StringLiteral("aarch64_pstate_sm_enabled"),
2693 StringLiteral("allocsize"),
2694 StringLiteral("alwaysinline"),
2695 StringLiteral("cold"),
2696 StringLiteral("convergent"),
2697 StringLiteral("fp-contract"),
2698 StringLiteral("frame-pointer"),
2699 StringLiteral("hot"),
2700 StringLiteral("inlinehint"),
2701 StringLiteral("instrument-function-entry"),
2702 StringLiteral("instrument-function-exit"),
2703 StringLiteral("modular-format"),
2704 StringLiteral("memory"),
2705 StringLiteral("minsize"),
2706 StringLiteral("no_caller_saved_registers"),
2707 StringLiteral("no-nans-fp-math"),
2708 StringLiteral("no-signed-zeros-fp-math"),
2709 StringLiteral("no-builtins"),
2710 StringLiteral("nocallback"),
2711 StringLiteral("noduplicate"),
2712 StringLiteral("noinline"),
2713 StringLiteral("noreturn"),
2714 StringLiteral("nounwind"),
2715 StringLiteral("optnone"),
2716 StringLiteral("optsize"),
2717 StringLiteral("returns_twice"),
2718 StringLiteral("save-reg-params"),
2719 StringLiteral("target-features"),
2720 StringLiteral("trap-func-name"),
2721 StringLiteral("tune-cpu"),
2722 StringLiteral("uwtable"),
2723 StringLiteral("vscale_range"),
2724 StringLiteral("willreturn"),
2725 StringLiteral("zero-call-used-regs"),
2726 StringLiteral("denormal_fpenv"),
2727};
2728
2729// List of LLVM IR attributes that are handled by prefix to map onto an MLIR
2730// LLVMFuncOp.
2731static constexpr std::array kExplicitLLVMFuncOpAttributePrefixes{
2732 StringLiteral("no-builtin-"),
2733};
2734
2735template <typename OpTy>
2737 const llvm::AttributeSet &attrs,
2738 OpTy target) {
2739 // 'no-builtins' is the complete collection, and overrides all the rest.
2740 if (attrs.hasAttribute("no-builtins")) {
2741 target.setNobuiltinsAttr(ArrayAttr::get(ctx, {}));
2742 return;
2743 }
2744
2746 for (llvm::Attribute attr : attrs) {
2747 // Attributes that are part of llvm directly (that is, have an AttributeKind
2748 // in the enum) shouldn't be checked.
2749 if (attr.hasKindAsEnum())
2750 continue;
2751
2752 StringRef val = attr.getKindAsString();
2753
2754 if (val.starts_with("no-builtin-"))
2755 nbAttrs.insert(
2756 StringAttr::get(ctx, val.drop_front(sizeof("no-builtin-") - 1)));
2757 }
2758
2759 if (!nbAttrs.empty())
2760 target.setNobuiltinsAttr(ArrayAttr::get(ctx, nbAttrs.getArrayRef()));
2761}
2762
2763template <typename OpTy>
2765 const llvm::AttributeSet &attrs, OpTy target) {
2766 llvm::Attribute attr = attrs.getAttribute(llvm::Attribute::AllocSize);
2767 if (!attr.isValid())
2768 return;
2769
2770 auto [elemSize, numElems] = attr.getAllocSizeArgs();
2771 if (numElems) {
2772 target.setAllocsizeAttr(
2773 DenseI32ArrayAttr::get(ctx, {static_cast<int32_t>(elemSize),
2774 static_cast<int32_t>(*numElems)}));
2775 } else {
2776 target.setAllocsizeAttr(
2777 DenseI32ArrayAttr::get(ctx, {static_cast<int32_t>(elemSize)}));
2778 }
2779}
2780
2781/// Converts LLVM attributes from `func` into MLIR attributes and adds them
2782/// to `funcOp` as passthrough attributes, skipping those listed in
2783/// `kExplicitLLVMFuncAttributes`.
2784static void processPassthroughAttrs(llvm::Function *func, LLVMFuncOp funcOp) {
2785 llvm::AttributeSet funcAttrs = func->getAttributes().getAttributes(
2786 llvm::AttributeList::AttrIndex::FunctionIndex);
2787 ArrayAttr passthroughAttr = convertLLVMAttributesToMLIR(
2788 funcOp.getLoc(), funcOp.getContext(), funcAttrs,
2790 if (!passthroughAttr.empty())
2791 funcOp.setPassthroughAttr(passthroughAttr);
2792}
2793
2795 LLVMFuncOp funcOp) {
2796 processMemoryEffects(func, funcOp);
2797 processDenormalFPEnv(func, funcOp);
2799
2800 if (func->hasFnAttribute(llvm::Attribute::NoInline))
2801 funcOp.setNoInline(true);
2802 if (func->hasFnAttribute(llvm::Attribute::AlwaysInline))
2803 funcOp.setAlwaysInline(true);
2804 if (func->hasFnAttribute(llvm::Attribute::InlineHint))
2805 funcOp.setInlineHint(true);
2806 if (func->hasFnAttribute(llvm::Attribute::OptimizeNone))
2807 funcOp.setOptimizeNone(true);
2808 if (func->hasFnAttribute(llvm::Attribute::Convergent))
2809 funcOp.setConvergent(true);
2810 if (func->hasFnAttribute(llvm::Attribute::NoUnwind))
2811 funcOp.setNoUnwind(true);
2812 if (func->hasFnAttribute(llvm::Attribute::WillReturn))
2813 funcOp.setWillReturn(true);
2814 if (func->hasFnAttribute(llvm::Attribute::NoReturn))
2815 funcOp.setNoreturn(true);
2816 if (func->hasFnAttribute(llvm::Attribute::OptimizeForSize))
2817 funcOp.setOptsize(true);
2818 if (func->hasFnAttribute("save-reg-params"))
2819 funcOp.setSaveRegParams(true);
2820 if (func->hasFnAttribute(llvm::Attribute::MinSize))
2821 funcOp.setMinsize(true);
2822 if (func->hasFnAttribute(llvm::Attribute::ReturnsTwice))
2823 funcOp.setReturnsTwice(true);
2824 if (func->hasFnAttribute(llvm::Attribute::Cold))
2825 funcOp.setCold(true);
2826 if (func->hasFnAttribute(llvm::Attribute::Hot))
2827 funcOp.setHot(true);
2828 if (func->hasFnAttribute(llvm::Attribute::NoDuplicate))
2829 funcOp.setNoduplicate(true);
2830 if (func->hasFnAttribute("no_caller_saved_registers"))
2831 funcOp.setNoCallerSavedRegisters(true);
2832 if (func->hasFnAttribute(llvm::Attribute::NoCallback))
2833 funcOp.setNocallback(true);
2834 if (llvm::Attribute attr = func->getFnAttribute("modular-format");
2835 attr.isStringAttribute())
2836 funcOp.setModularFormat(StringAttr::get(context, attr.getValueAsString()));
2837 if (llvm::Attribute attr = func->getFnAttribute("zero-call-used-regs");
2838 attr.isStringAttribute())
2839 funcOp.setZeroCallUsedRegsAttr(
2840 StringAttr::get(context, attr.getValueAsString()));
2841
2842 if (func->hasFnAttribute("aarch64_pstate_sm_enabled"))
2843 funcOp.setArmStreaming(true);
2844 else if (func->hasFnAttribute("aarch64_pstate_sm_body"))
2845 funcOp.setArmLocallyStreaming(true);
2846 else if (func->hasFnAttribute("aarch64_pstate_sm_compatible"))
2847 funcOp.setArmStreamingCompatible(true);
2848
2849 if (func->hasFnAttribute("aarch64_new_za"))
2850 funcOp.setArmNewZa(true);
2851 else if (func->hasFnAttribute("aarch64_in_za"))
2852 funcOp.setArmInZa(true);
2853 else if (func->hasFnAttribute("aarch64_out_za"))
2854 funcOp.setArmOutZa(true);
2855 else if (func->hasFnAttribute("aarch64_inout_za"))
2856 funcOp.setArmInoutZa(true);
2857 else if (func->hasFnAttribute("aarch64_preserves_za"))
2858 funcOp.setArmPreservesZa(true);
2859
2860 convertNoBuiltinAttrs(context, func->getAttributes().getFnAttrs(), funcOp);
2861 convertAllocsizeAttr(context, func->getAttributes().getFnAttrs(), funcOp);
2862
2863 llvm::Attribute attr = func->getFnAttribute(llvm::Attribute::VScaleRange);
2864 if (attr.isValid()) {
2865 MLIRContext *context = funcOp.getContext();
2866 auto intTy = IntegerType::get(context, 32);
2867 funcOp.setVscaleRangeAttr(LLVM::VScaleRangeAttr::get(
2868 context, IntegerAttr::get(intTy, attr.getVScaleRangeMin()),
2869 IntegerAttr::get(intTy, attr.getVScaleRangeMax().value_or(0))));
2870 }
2871
2872 // Process frame-pointer attribute.
2873 if (func->hasFnAttribute("frame-pointer")) {
2874 StringRef stringRefFramePointerKind =
2875 func->getFnAttribute("frame-pointer").getValueAsString();
2876 funcOp.setFramePointerAttr(LLVM::FramePointerKindAttr::get(
2877 funcOp.getContext(), LLVM::framePointerKind::symbolizeFramePointerKind(
2878 stringRefFramePointerKind)
2879 .value()));
2880 }
2881
2882 if (llvm::Attribute attr = func->getFnAttribute("target-cpu");
2883 attr.isStringAttribute())
2884 funcOp.setTargetCpuAttr(StringAttr::get(context, attr.getValueAsString()));
2885
2886 if (llvm::Attribute attr = func->getFnAttribute("tune-cpu");
2887 attr.isStringAttribute())
2888 funcOp.setTuneCpuAttr(StringAttr::get(context, attr.getValueAsString()));
2889
2890 if (llvm::Attribute attr = func->getFnAttribute("target-features");
2891 attr.isStringAttribute())
2892 funcOp.setTargetFeaturesAttr(
2893 LLVM::TargetFeaturesAttr::get(context, attr.getValueAsString()));
2894
2895 if (llvm::Attribute attr = func->getFnAttribute("reciprocal-estimates");
2896 attr.isStringAttribute())
2897 funcOp.setReciprocalEstimatesAttr(
2898 StringAttr::get(context, attr.getValueAsString()));
2899
2900 if (llvm::Attribute attr = func->getFnAttribute("prefer-vector-width");
2901 attr.isStringAttribute())
2902 funcOp.setPreferVectorWidth(attr.getValueAsString());
2903
2904 if (llvm::Attribute attr = func->getFnAttribute("no-nans-fp-math");
2905 attr.isStringAttribute())
2906 funcOp.setNoNansFpMath(attr.getValueAsBool());
2907
2908 if (llvm::Attribute attr = func->getFnAttribute("instrument-function-entry");
2909 attr.isStringAttribute())
2910 funcOp.setInstrumentFunctionEntry(
2911 StringAttr::get(context, attr.getValueAsString()));
2912
2913 if (llvm::Attribute attr = func->getFnAttribute("instrument-function-exit");
2914 attr.isStringAttribute())
2915 funcOp.setInstrumentFunctionExit(
2916 StringAttr::get(context, attr.getValueAsString()));
2917
2918 if (llvm::Attribute attr = func->getFnAttribute("no-signed-zeros-fp-math");
2919 attr.isStringAttribute())
2920 funcOp.setNoSignedZerosFpMath(attr.getValueAsBool());
2921
2922 if (llvm::Attribute attr = func->getFnAttribute("fp-contract");
2923 attr.isStringAttribute())
2924 funcOp.setFpContractAttr(StringAttr::get(context, attr.getValueAsString()));
2925
2926 if (func->hasUWTable()) {
2927 ::llvm::UWTableKind uwtableKind = func->getUWTableKind();
2928 funcOp.setUwtableKindAttr(LLVM::UWTableKindAttr::get(
2929 funcOp.getContext(), convertUWTableKindFromLLVM(uwtableKind)));
2930 }
2931}
2932
2933DictionaryAttr
2934ModuleImport::convertArgOrResultAttrSet(llvm::AttributeSet llvmAttrSet) {
2935 SmallVector<NamedAttribute> paramAttrs;
2936 for (auto [llvmKind, mlirName] : getAttrKindToNameMapping()) {
2937 auto llvmAttr = llvmAttrSet.getAttribute(llvmKind);
2938 // Skip attributes that are not attached.
2939 if (!llvmAttr.isValid())
2940 continue;
2941
2942 // TODO: Import captures(none) as a nocapture unit attribute until the
2943 // LLVM dialect switches to the captures representation.
2944 if (llvmAttr.hasKindAsEnum() &&
2945 llvmAttr.getKindAsEnum() == llvm::Attribute::Captures) {
2946 if (llvm::capturesNothing(llvmAttr.getCaptureInfo()))
2947 paramAttrs.push_back(
2948 builder.getNamedAttr(mlirName, builder.getUnitAttr()));
2949 continue;
2950 }
2951
2952 Attribute mlirAttr;
2953 if (llvmAttr.isTypeAttribute())
2954 mlirAttr = TypeAttr::get(convertType(llvmAttr.getValueAsType()));
2955 else if (llvmAttr.isIntAttribute())
2956 mlirAttr = builder.getI64IntegerAttr(llvmAttr.getValueAsInt());
2957 else if (llvmAttr.isEnumAttribute())
2958 mlirAttr = builder.getUnitAttr();
2959 else if (llvmAttr.isConstantRangeAttribute()) {
2960 const llvm::ConstantRange &value = llvmAttr.getValueAsConstantRange();
2961 mlirAttr = builder.getAttr<LLVM::ConstantRangeAttr>(value.getLower(),
2962 value.getUpper());
2963 } else {
2964 llvm_unreachable("unexpected parameter attribute kind");
2965 }
2966 paramAttrs.push_back(builder.getNamedAttr(mlirName, mlirAttr));
2967 }
2968
2969 return builder.getDictionaryAttr(paramAttrs);
2970}
2971
2972void ModuleImport::convertArgAndResultAttrs(llvm::Function *func,
2973 LLVMFuncOp funcOp) {
2974 auto llvmAttrs = func->getAttributes();
2975 for (size_t i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
2976 llvm::AttributeSet llvmArgAttrs = llvmAttrs.getParamAttrs(i);
2977 funcOp.setArgAttrs(i, convertArgOrResultAttrSet(llvmArgAttrs));
2978 }
2979 // Convert the result attributes and attach them wrapped in an ArrayAttribute
2980 // to the funcOp.
2981 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
2982 if (!llvmResAttr.hasAttributes())
2983 return;
2984 funcOp.setResAttrsAttr(
2985 builder.getArrayAttr({convertArgOrResultAttrSet(llvmResAttr)}));
2986}
2987
2989 llvm::CallBase *call, ArgAndResultAttrsOpInterface attrsOp,
2990 ArrayRef<unsigned> immArgPositions) {
2991 // Compute the set of immediate argument positions.
2992 llvm::SmallDenseSet<unsigned> immArgPositionsSet(immArgPositions.begin(),
2993 immArgPositions.end());
2994 // Convert the argument attributes and filter out immediate arguments.
2995 llvm::AttributeList llvmAttrs = call->getAttributes();
2996 SmallVector<llvm::AttributeSet> llvmArgAttrsSet;
2997 bool anyArgAttrs = false;
2998 for (size_t i = 0, e = call->arg_size(); i < e; ++i) {
2999 // Skip immediate arguments.
3000 if (immArgPositionsSet.contains(i))
3001 continue;
3002 llvmArgAttrsSet.emplace_back(llvmAttrs.getParamAttrs(i));
3003 if (llvmArgAttrsSet.back().hasAttributes())
3004 anyArgAttrs = true;
3005 }
3006 auto getArrayAttr = [&](ArrayRef<DictionaryAttr> dictAttrs) {
3008 for (auto &dict : dictAttrs)
3009 attrs.push_back(dict ? dict : builder.getDictionaryAttr({}));
3010 return builder.getArrayAttr(attrs);
3011 };
3012 if (anyArgAttrs) {
3014 for (auto &llvmArgAttrs : llvmArgAttrsSet)
3015 argAttrs.emplace_back(convertArgOrResultAttrSet(llvmArgAttrs));
3016 attrsOp.setArgAttrsAttr(getArrayAttr(argAttrs));
3017 }
3018
3019 // Convert the result attributes.
3020 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
3021 if (!llvmResAttr.hasAttributes())
3022 return;
3023 DictionaryAttr resAttrs = convertArgOrResultAttrSet(llvmResAttr);
3024 attrsOp.setResAttrsAttr(getArrayAttr({resAttrs}));
3025}
3026
3027template <typename Op>
3028static LogicalResult convertCallBaseAttributes(llvm::CallBase *inst, Op op) {
3029 op.setCConv(convertCConvFromLLVM(inst->getCallingConv()));
3030 return success();
3031}
3032
3033LogicalResult ModuleImport::convertInvokeAttributes(llvm::InvokeInst *inst,
3034 InvokeOp op) {
3035 return convertCallBaseAttributes(inst, op);
3036}
3037
3038LogicalResult ModuleImport::convertCallAttributes(llvm::CallInst *inst,
3039 CallOp op) {
3040 setFastmathFlagsAttr(inst, op.getOperation());
3041 // Query the attributes directly instead of using `inst->getFnAttr(Kind)`, the
3042 // latter does additional lookup to the parent and inherits, changing the
3043 // semantics too early.
3044 llvm::AttributeList callAttrs = inst->getAttributes();
3045
3046 op.setTailCallKind(convertTailCallKindFromLLVM(inst->getTailCallKind()));
3047 op.setConvergent(callAttrs.getFnAttr(llvm::Attribute::Convergent).isValid());
3048 op.setNoUnwind(callAttrs.getFnAttr(llvm::Attribute::NoUnwind).isValid());
3049 op.setWillReturn(callAttrs.getFnAttr(llvm::Attribute::WillReturn).isValid());
3050 op.setNoreturn(callAttrs.getFnAttr(llvm::Attribute::NoReturn).isValid());
3051 op.setOptsize(
3052 callAttrs.getFnAttr(llvm::Attribute::OptimizeForSize).isValid());
3053 op.setSaveRegParams(callAttrs.getFnAttr("save-reg-params").isValid());
3054 op.setNobuiltin(callAttrs.getFnAttr(llvm::Attribute::NoBuiltin).isValid());
3055 op.setMinsize(callAttrs.getFnAttr(llvm::Attribute::MinSize).isValid());
3056
3057 op.setReturnsTwice(
3058 callAttrs.getFnAttr(llvm::Attribute::ReturnsTwice).isValid());
3059 op.setHot(callAttrs.getFnAttr(llvm::Attribute::Hot).isValid());
3060 op.setCold(callAttrs.getFnAttr(llvm::Attribute::Cold).isValid());
3061 op.setNoduplicate(
3062 callAttrs.getFnAttr(llvm::Attribute::NoDuplicate).isValid());
3063 op.setNoCallerSavedRegisters(
3064 callAttrs.getFnAttr("no_caller_saved_registers").isValid());
3065 op.setNocallback(callAttrs.getFnAttr(llvm::Attribute::NoCallback).isValid());
3066
3067 if (llvm::Attribute attr = callAttrs.getFnAttr("modular-format");
3068 attr.isStringAttribute())
3069 op.setModularFormat(StringAttr::get(context, attr.getValueAsString()));
3070 if (llvm::Attribute attr = callAttrs.getFnAttr("zero-call-used-regs");
3071 attr.isStringAttribute())
3072 op.setZeroCallUsedRegsAttr(
3073 StringAttr::get(context, attr.getValueAsString()));
3074 if (llvm::Attribute attr = callAttrs.getFnAttr("trap-func-name");
3075 attr.isStringAttribute())
3076 op.setTrapFuncNameAttr(StringAttr::get(context, attr.getValueAsString()));
3077 op.setNoInline(callAttrs.getFnAttr(llvm::Attribute::NoInline).isValid());
3078 op.setAlwaysInline(
3079 callAttrs.getFnAttr(llvm::Attribute::AlwaysInline).isValid());
3080 op.setInlineHint(callAttrs.getFnAttr(llvm::Attribute::InlineHint).isValid());
3081
3082 llvm::MemoryEffects memEffects = inst->getMemoryEffects();
3083 ModRefInfo othermem = convertModRefInfoFromLLVM(
3084 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
3085 ModRefInfo argMem = convertModRefInfoFromLLVM(
3086 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
3087 ModRefInfo inaccessibleMem = convertModRefInfoFromLLVM(
3088 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
3089 ModRefInfo errnoMem = convertModRefInfoFromLLVM(
3090 memEffects.getModRef(llvm::MemoryEffects::Location::ErrnoMem));
3091 ModRefInfo targetMem0 = convertModRefInfoFromLLVM(
3092 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem0));
3093 ModRefInfo targetMem1 = convertModRefInfoFromLLVM(
3094 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem1));
3095 auto memAttr =
3096 MemoryEffectsAttr::get(op.getContext(), othermem, argMem, inaccessibleMem,
3097 errnoMem, targetMem0, targetMem1);
3098 // Only set the attribute when it does not match the default value.
3099 if (!memAttr.isReadWrite())
3100 op.setMemoryEffectsAttr(memAttr);
3101
3102 convertNoBuiltinAttrs(op.getContext(), callAttrs.getFnAttrs(), op);
3103 convertAllocsizeAttr(op.getContext(), callAttrs.getFnAttrs(), op);
3104
3105 return convertCallBaseAttributes(inst, op);
3106}
3107
3108LogicalResult ModuleImport::processFunction(llvm::Function *func) {
3109 clearRegionState();
3110
3111 auto functionType =
3112 dyn_cast<LLVMFunctionType>(convertType(func->getFunctionType()));
3113 if (func->isIntrinsic() &&
3114 iface.isConvertibleIntrinsic(func->getIntrinsicID()))
3115 return success();
3116
3117 bool dsoLocal = func->isDSOLocal();
3118 CConv cconv = convertCConvFromLLVM(func->getCallingConv());
3119
3120 // Insert the function at the end of the module.
3121 OpBuilder::InsertionGuard guard(builder);
3122 builder.setInsertionPointToEnd(mlirModule.getBody());
3123
3124 Location loc = debugImporter->translateFuncLocation(func);
3125 LLVMFuncOp funcOp = LLVMFuncOp::create(
3126 builder, loc, func->getName(), functionType,
3127 convertLinkageFromLLVM(func->getLinkage()), dsoLocal, cconv);
3128
3130
3131 if (FlatSymbolRefAttr personality = getPersonalityAsAttr(func))
3132 funcOp.setPersonalityAttr(personality);
3133 else if (func->hasPersonalityFn())
3134 emitWarning(funcOp.getLoc(), "could not deduce personality, skipping it");
3135
3136 if (func->hasGC())
3137 funcOp.setGarbageCollector(StringRef(func->getGC()));
3138
3139 if (func->hasAtLeastLocalUnnamedAddr())
3140 funcOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(func->getUnnamedAddr()));
3141
3142 if (func->hasSection())
3143 funcOp.setSection(StringRef(func->getSection()));
3144
3145 funcOp.setVisibility_(convertVisibilityFromLLVM(func->getVisibility()));
3146
3147 if (func->hasComdat())
3148 funcOp.setComdatAttr(comdatMapping.lookup(func->getComdat()));
3149
3150 if (llvm::MaybeAlign maybeAlign = func->getAlign())
3151 funcOp.setAlignment(maybeAlign->value());
3152
3153 // Handle Function attributes.
3155
3156 // Convert non-debug metadata by using the dialect interface.
3158 func->getAllMetadata(allMetadata);
3159 for (auto &[kind, node] : allMetadata) {
3160 if (!iface.isConvertibleMetadata(kind))
3161 continue;
3162 if (failed(iface.setMetadataAttrs(builder, kind, node, funcOp, *this))) {
3163 emitWarning(funcOp.getLoc())
3164 << "unhandled function metadata: " << diagMD(node, llvmModule.get())
3165 << " on " << diag(*func);
3166 }
3167 }
3168
3169 if (func->isDeclaration())
3170 return success();
3171
3172 // Collect the set of basic blocks reachable from the function's entry block.
3173 // This step is crucial as LLVM IR can contain unreachable blocks that
3174 // self-dominate. As a result, an operation might utilize a variable it
3175 // defines, which the import does not support. Given that MLIR lacks block
3176 // label support, we can safely remove unreachable blocks, as there are no
3177 // indirect branch instructions that could potentially target these blocks.
3178 llvm::df_iterator_default_set<llvm::BasicBlock *> reachable;
3179 for (llvm::BasicBlock *basicBlock : llvm::depth_first_ext(func, reachable))
3180 (void)basicBlock;
3181
3182 // Eagerly create all reachable blocks.
3183 SmallVector<llvm::BasicBlock *> reachableBasicBlocks;
3184 for (llvm::BasicBlock &basicBlock : *func) {
3185 // Skip unreachable blocks.
3186 if (!reachable.contains(&basicBlock)) {
3187 if (basicBlock.hasAddressTaken())
3188 return emitError(funcOp.getLoc())
3189 << "unreachable block '" << basicBlock.getName()
3190 << "' with address taken";
3191 continue;
3192 }
3193 Region &body = funcOp.getBody();
3194 Block *block = builder.createBlock(&body, body.end());
3195 mapBlock(&basicBlock, block);
3196 reachableBasicBlocks.push_back(&basicBlock);
3197 }
3198
3199 // Add function arguments to the entry block.
3200 for (const auto &it : llvm::enumerate(func->args())) {
3201 BlockArgument blockArg = funcOp.getFunctionBody().addArgument(
3202 functionType.getParamType(it.index()), funcOp.getLoc());
3203 mapValue(&it.value(), blockArg);
3204 }
3205
3206 // Process the blocks in topological order. The ordered traversal ensures
3207 // operands defined in a dominating block have a valid mapping to an MLIR
3208 // value once a block is translated.
3210 getTopologicallySortedBlocks(reachableBasicBlocks);
3211 setConstantInsertionPointToStart(lookupBlock(blocks.front()));
3212 for (llvm::BasicBlock *basicBlock : blocks)
3213 if (failed(processBasicBlock(basicBlock, lookupBlock(basicBlock))))
3214 return failure();
3215
3216 // Process the debug intrinsics that require a delayed conversion after
3217 // everything else was converted.
3218 if (failed(processDebugIntrinsics()))
3219 return failure();
3220
3221 // Process the debug records that require a delayed conversion after
3222 // everything else was converted.
3223 if (failed(processDebugRecords()))
3224 return failure();
3225
3226 return success();
3227}
3228
3229/// Checks if `dbgIntr` is a kill location that holds metadata instead of an SSA
3230/// value.
3231static bool isMetadataKillLocation(llvm::DbgVariableIntrinsic *dbgIntr) {
3232 if (!dbgIntr->isKillLocation())
3233 return false;
3234 llvm::Value *value = dbgIntr->getArgOperand(0);
3235 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
3236 if (!nodeAsVal)
3237 return false;
3238 return !isa<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
3239}
3240
3241/// Ensure that the debug intrinsic is inserted right after the operand
3242/// definition. Otherwise, the operand might not necessarily dominate the
3243/// intrinsic. If the defining operation is a terminator, insert the intrinsic
3244/// into a dominated block.
3246 mlir::OpBuilder &builder, DominanceInfo &domInfo, Value argOperand) {
3247 if (Operation *op = argOperand.getDefiningOp();
3248 op && op->hasTrait<OpTrait::IsTerminator>()) {
3249 // Find a dominated block that can hold the debug intrinsic.
3250 auto dominatedBlocks = domInfo.getNode(op->getBlock())->children();
3251 // If no block is dominated by the terminator, this intrinisc cannot be
3252 // converted.
3253 if (dominatedBlocks.empty())
3254 return failure();
3255 // Set insertion point before the terminator, to avoid inserting something
3256 // before landingpads.
3257 Block *dominatedBlock = (*dominatedBlocks.begin())->getBlock();
3258 builder.setInsertionPoint(dominatedBlock->getTerminator());
3259 } else {
3260 Value insertPt = argOperand;
3261 if (auto blockArg = dyn_cast<BlockArgument>(argOperand)) {
3262 // The value might be coming from a phi node and is now a block argument,
3263 // which means the insertion point is set to the start of the block. If
3264 // this block is a target destination of an invoke, the insertion point
3265 // must happen after the landing pad operation.
3266 Block *insertionBlock = argOperand.getParentBlock();
3267 if (!insertionBlock->empty() &&
3268 isa<LandingpadOp>(insertionBlock->front()))
3269 insertPt = cast<LandingpadOp>(insertionBlock->front()).getRes();
3270 }
3271
3272 builder.setInsertionPointAfterValue(insertPt);
3273 }
3274 return success();
3275}
3276
3277std::tuple<DILocalVariableAttr, DIExpressionAttr, Value>
3278ModuleImport::processDebugOpArgumentsAndInsertionPt(
3279 Location loc,
3280 llvm::function_ref<FailureOr<Value>()> convertArgOperandToValue,
3281 llvm::Value *address,
3282 llvm::PointerUnion<llvm::Value *, llvm::DILocalVariable *> variable,
3283 llvm::DIExpression *expression, DominanceInfo &domInfo) {
3284 // Drop debug intrinsics if the associated debug information cannot be
3285 // translated due to an unsupported construct.
3286 DILocalVariableAttr localVarAttr = matchLocalVariableAttr(variable);
3287 if (!localVarAttr)
3288 return {};
3289 FailureOr<Value> argOperand = convertArgOperandToValue();
3290 if (failed(argOperand)) {
3291 emitError(loc) << "failed to convert a debug operand: " << diag(*address);
3292 return {};
3293 }
3294
3295 if (setDebugIntrinsicBuilderInsertionPoint(builder, domInfo, *argOperand)
3296 .failed())
3297 return {};
3298
3299 return {localVarAttr, debugImporter->translateExpression(expression),
3300 *argOperand};
3301}
3302
3303LogicalResult
3304ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr,
3305 DominanceInfo &domInfo) {
3306 Location loc = translateLoc(dbgIntr->getDebugLoc());
3307 auto emitUnsupportedWarning = [&]() {
3308 if (emitExpensiveWarnings)
3309 emitWarning(loc) << "dropped intrinsic: " << diag(*dbgIntr);
3310 return success();
3311 };
3312
3313 OpBuilder::InsertionGuard guard(builder);
3314 auto convertArgOperandToValue = [&]() {
3315 return convertMetadataValue(dbgIntr->getArgOperand(0));
3316 };
3317
3318 // Drop debug intrinsics with an argument list.
3319 // TODO: Support this case.
3320 if (dbgIntr->hasArgList())
3321 return emitUnsupportedWarning();
3322
3323 // Drop debug intrinsics with kill locations that have metadata nodes as
3324 // location operand, which cannot be converted to poison as the type cannot be
3325 // reconstructed.
3326 // TODO: Support this case.
3327 if (isMetadataKillLocation(dbgIntr))
3328 return emitUnsupportedWarning();
3329
3330 auto [localVariableAttr, locationExprAttr, locVal] =
3331 processDebugOpArgumentsAndInsertionPt(
3332 loc, convertArgOperandToValue, dbgIntr->getArgOperand(0),
3333 dbgIntr->getArgOperand(1), dbgIntr->getExpression(), domInfo);
3334
3335 if (!localVariableAttr)
3336 return emitUnsupportedWarning();
3337
3338 if (!locVal) // Expected if localVariableAttr is present.
3339 return failure();
3340
3341 Operation *op = nullptr;
3342 if (isa<llvm::DbgDeclareInst>(dbgIntr))
3343 op = LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,
3344 locationExprAttr);
3345 else if (isa<llvm::DbgValueInst>(dbgIntr))
3346 op = LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,
3347 locationExprAttr);
3348 else
3349 return emitUnsupportedWarning();
3350
3351 mapNoResultOp(dbgIntr, op);
3352 setNonDebugMetadataAttrs(dbgIntr, op);
3353 return success();
3354}
3355
3356LogicalResult
3357ModuleImport::processDebugRecord(llvm::DbgVariableRecord &dbgRecord,
3358 DominanceInfo &domInfo) {
3359 OpBuilder::InsertionGuard guard(builder);
3360 Location loc = translateLoc(dbgRecord.getDebugLoc());
3361 auto emitUnsupportedWarning = [&]() -> LogicalResult {
3362 if (!emitExpensiveWarnings)
3363 return success();
3364 std::string options;
3365 llvm::raw_string_ostream optionsStream(options);
3366 dbgRecord.print(optionsStream);
3367 emitWarning(loc) << "unhandled debug variable record "
3368 << optionsStream.str();
3369 return success();
3370 };
3371
3372 // Drop debug records with an argument list.
3373 // TODO: Support this case.
3374 if (dbgRecord.hasArgList())
3375 return emitUnsupportedWarning();
3376
3377 // Drop all other debug records with a address operand that cannot be
3378 // converted to an SSA value such as an empty metadata node.
3379 // TODO: Support this case.
3380 if (!dbgRecord.getAddress())
3381 return emitUnsupportedWarning();
3382
3383 auto convertArgOperandToValue = [&]() -> FailureOr<Value> {
3384 llvm::Value *value = dbgRecord.getAddress();
3385
3386 // Return the mapped value if it has been converted before.
3387 auto it = valueMapping.find(value);
3388 if (it != valueMapping.end())
3389 return it->getSecond();
3390
3391 // Convert constants such as immediate values that have no mapping yet.
3392 if (auto *constant = dyn_cast<llvm::Constant>(value))
3393 return convertConstantExpr(constant);
3394 return failure();
3395 };
3396
3397 auto [localVariableAttr, locationExprAttr, locVal] =
3398 processDebugOpArgumentsAndInsertionPt(
3399 loc, convertArgOperandToValue, dbgRecord.getAddress(),
3400 dbgRecord.getVariable(), dbgRecord.getExpression(), domInfo);
3401
3402 if (!localVariableAttr)
3403 return emitUnsupportedWarning();
3404
3405 if (!locVal) // Expected if localVariableAttr is present.
3406 return failure();
3407
3408 if (dbgRecord.isDbgDeclare())
3409 LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,
3410 locationExprAttr);
3411 else if (dbgRecord.isDbgValue())
3412 LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,
3413 locationExprAttr);
3414 else // isDbgAssign
3415 return emitUnsupportedWarning();
3416
3417 return success();
3418}
3419
3420LogicalResult ModuleImport::processDebugIntrinsics() {
3421 DominanceInfo domInfo;
3422 for (llvm::Instruction *inst : debugIntrinsics) {
3423 auto *intrCall = cast<llvm::DbgVariableIntrinsic>(inst);
3424 if (failed(processDebugIntrinsic(intrCall, domInfo)))
3425 return failure();
3426 }
3427 return success();
3428}
3429
3430LogicalResult ModuleImport::processDebugRecords() {
3431 DominanceInfo domInfo;
3432 for (llvm::DbgVariableRecord *dbgRecord : dbgRecords)
3433 if (failed(processDebugRecord(*dbgRecord, domInfo)))
3434 return failure();
3435 dbgRecords.clear();
3436 return success();
3437}
3438
3439LogicalResult ModuleImport::processBasicBlock(llvm::BasicBlock *bb,
3440 Block *block) {
3441 builder.setInsertionPointToStart(block);
3442 for (llvm::Instruction &inst : *bb) {
3443 if (failed(processInstruction(&inst)))
3444 return failure();
3445
3446 // Skip additional processing when the instructions is a debug intrinsics
3447 // that was not yet converted.
3448 if (debugIntrinsics.contains(&inst))
3449 continue;
3450
3451 // Set the non-debug metadata attributes on the imported operation and emit
3452 // a warning if an instruction other than a phi instruction is dropped
3453 // during the import.
3454 if (Operation *op = lookupOperation(&inst)) {
3455 setNonDebugMetadataAttrs(&inst, op);
3456 } else if (inst.getOpcode() != llvm::Instruction::PHI) {
3457 if (emitExpensiveWarnings) {
3458 Location loc = debugImporter->translateLoc(inst.getDebugLoc());
3459 emitWarning(loc) << "dropped instruction: " << diag(inst);
3460 }
3461 }
3462 }
3463
3464 if (bb->hasAddressTaken()) {
3465 OpBuilder::InsertionGuard guard(builder);
3466 builder.setInsertionPointToStart(block);
3467 BlockTagOp::create(builder, block->getParentOp()->getLoc(),
3468 BlockTagAttr::get(context, bb->getNumber()));
3469 }
3470 return success();
3471}
3472
3473FailureOr<SmallVector<AccessGroupAttr>>
3474ModuleImport::lookupAccessGroupAttrs(const llvm::MDNode *node) const {
3475 return loopAnnotationImporter->lookupAccessGroupAttrs(node);
3476}
3477
3478LoopAnnotationAttr
3480 Location loc) const {
3481 return loopAnnotationImporter->translateLoopAnnotation(node, loc);
3482}
3483
3484FailureOr<DereferenceableAttr>
3486 unsigned kindID) {
3487 Location loc = mlirModule.getLoc();
3488
3489 // The only operand should be a constant integer representing the number of
3490 // dereferenceable bytes.
3491 if (node->getNumOperands() != 1)
3492 return emitError(loc) << "dereferenceable metadata must have one operand: "
3493 << diagMD(node, llvmModule.get());
3494
3495 auto *numBytesMD = dyn_cast<llvm::ConstantAsMetadata>(node->getOperand(0));
3496 auto *numBytesCst = dyn_cast<llvm::ConstantInt>(numBytesMD->getValue());
3497 if (!numBytesCst || !numBytesCst->getValue().isNonNegative())
3498 return emitError(loc) << "dereferenceable metadata operand must be a "
3499 "non-negative constant integer: "
3500 << diagMD(node, llvmModule.get());
3501
3502 bool mayBeNull = kindID == llvm::LLVMContext::MD_dereferenceable_or_null;
3503 auto derefAttr = builder.getAttr<DereferenceableAttr>(
3504 numBytesCst->getZExtValue(), mayBeNull);
3505
3506 return derefAttr;
3507}
3508
3510 std::unique_ptr<llvm::Module> llvmModule, MLIRContext *context,
3511 bool emitExpensiveWarnings, bool dropDICompositeTypeElements,
3512 bool loadAllDialects, bool preferUnregisteredIntrinsics,
3513 bool importStructsAsLiterals) {
3514 // Preload all registered dialects to allow the import to iterate the
3515 // registered LLVMImportDialectInterface implementations and query the
3516 // supported LLVM IR constructs before starting the translation. Assumes the
3517 // LLVM and DLTI dialects that convert the core LLVM IR constructs have been
3518 // registered before.
3519 assert(llvm::is_contained(context->getAvailableDialects(),
3520 LLVMDialect::getDialectNamespace()));
3521 assert(llvm::is_contained(context->getAvailableDialects(),
3522 DLTIDialect::getDialectNamespace()));
3523 if (loadAllDialects)
3524 context->loadAllAvailableDialects();
3525 OwningOpRef<ModuleOp> module(ModuleOp::create(FileLineColLoc::get(
3526 StringAttr::get(context, llvmModule->getSourceFileName()), /*line=*/0,
3527 /*column=*/0)));
3528
3529 ModuleImport moduleImport(module.get(), std::move(llvmModule),
3530 emitExpensiveWarnings, dropDICompositeTypeElements,
3531 preferUnregisteredIntrinsics,
3532 importStructsAsLiterals);
3533 if (failed(moduleImport.initializeImportInterface()))
3534 return {};
3535 if (failed(moduleImport.convertDataLayout()))
3536 return {};
3537 if (failed(moduleImport.convertComdats()))
3538 return {};
3539 if (failed(moduleImport.convertMetadata()))
3540 return {};
3541 if (failed(moduleImport.convertGlobals()))
3542 return {};
3543 if (failed(moduleImport.convertFunctions()))
3544 return {};
3545 if (failed(moduleImport.convertAliases()))
3546 return {};
3547 if (failed(moduleImport.convertIFuncs()))
3548 return {};
3549 moduleImport.convertTargetTriple();
3550 moduleImport.convertModuleLevelAsm();
3551 return module;
3552}
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:309
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:749
Location getLoc()
The source location the operation was defined or derived from.
Definition Operation.h:223
This class acts as an owning reference to an op, and will automatically destroy the held op on destru...
Definition OwningOpRef.h:29
OpTy get() const
Allow accessing the internal op.
Definition OwningOpRef.h:51
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition Region.h:26
iterator end()
Definition Region.h:56
static SmallString< N > generateSymbolName(StringRef name, UniqueChecker uniqueChecker, unsigned &uniquingCounter)
Generate a unique symbol name.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
MLIRContext * getContext() const
Return the MLIRContext in which this type was uniqued.
Definition Types.cpp:35
bool isIntOrFloat() const
Return true if this is an integer (of any signedness) or a float type.
Definition Types.cpp: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.