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