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