36#include "llvm/ADT/SmallVector.h"
37#include "llvm/IR/Type.h"
38#include "llvm/Support/DebugLog.h"
39#include "llvm/Support/FormatVariadic.h"
43#define GEN_PASS_DEF_CONVERTFUNCTOLLVMPASS
44#define GEN_PASS_DEF_SETLLVMMODULEDATALAYOUTPASS
45#include "mlir/Conversion/Passes.h.inc"
50#define PASS_NAME "convert-func-to-llvm"
51#define DEBUG_TYPE PASS_NAME
66 name == LLVM::LLVMDialect::getReadnoneAttrName();
88static FailureOr<LoweredFuncAttrs>
93 llvm::SmallDenseSet<StringRef> odsAttrNames(
94 LLVM::LLVMFuncOp::getAttributeNames().begin(),
95 LLVM::LLVMFuncOp::getAttributeNames().end());
100 StringRef attrName = attr.getName().strref();
102 if (odsAttrNames.contains(attrName)) {
103 LDBG() <<
"LLVM specific attributes: " << attrName
104 <<
"should use llvm.* prefix, discarding it";
108 StringRef inherent = attrName;
109 if (inherent.consume_front(
"llvm.") && odsAttrNames.contains(inherent))
110 inherentAttrs.
set(inherent, attr.getValue());
116 if (!inherentAttrs.
empty()) {
119 return func.emitOpError(
"invalid llvm.func property");
121 if (failed(LLVM::LLVMFuncOp::setPropertiesFromAttr(lowered.
properties, dict,
130 FunctionOpInterface srcFunc,
132 LLVM::LLVMFuncOp::Properties &props) {
135 props.function_type = TypeAttr::get(llvmFuncType);
136 props.setCConv(LLVM::CConvAttr::get(ctx, LLVM::CConv::C));
141 FunctionOpInterface funcOp,
142 LLVM::LLVMFuncOp wrapperFuncOp) {
143 auto argAttrs = funcOp.getAllArgAttrs();
144 if (!resultStructType) {
145 if (
auto resAttrs = funcOp.getAllResultAttrs())
146 wrapperFuncOp.setAllResultAttrs(resAttrs);
148 wrapperFuncOp.setAllArgAttrs(argAttrs);
155 argAttributes.append(argAttrs.begin(), argAttrs.end());
156 wrapperFuncOp.setAllArgAttrs(argAttributes);
159 cast<FunctionOpInterface>(wrapperFuncOp.getOperation())
160 .setVisibility(funcOp.getVisibility());
173 FunctionOpInterface funcOp,
174 LLVM::LLVMFuncOp newFuncOp) {
175 auto type = cast<FunctionType>(funcOp.getFunctionType());
176 auto [wrapperFuncType, resultStructType] =
182 auto wrapperFuncOp = LLVM::LLVMFuncOp::create(
183 rewriter, loc, llvm::formatv(
"_mlir_ciface_{0}", funcOp.getName()).str(),
184 wrapperFuncType, LLVM::Linkage::External,
false,
185 LLVM::CConv::C,
nullptr, attributes);
192 size_t argOffset = resultStructType ? 1 : 0;
193 for (
auto [
index, argType] : llvm::enumerate(type.getInputs())) {
194 Value arg = wrapperFuncOp.getArgument(
index + argOffset);
195 if (
auto memrefType = dyn_cast<MemRefType>(argType)) {
196 Value loaded = LLVM::LoadOp::create(
197 rewriter, loc, typeConverter.convertType(memrefType), arg);
201 if (isa<UnrankedMemRefType>(argType)) {
202 Value loaded = LLVM::LoadOp::create(
203 rewriter, loc, typeConverter.convertType(argType), arg);
211 auto call = LLVM::CallOp::create(rewriter, loc, newFuncOp, args);
213 if (resultStructType) {
214 LLVM::StoreOp::create(rewriter, loc, call.getResult(),
215 wrapperFuncOp.getArgument(0));
216 LLVM::ReturnOp::create(rewriter, loc,
ValueRange{});
218 LLVM::ReturnOp::create(rewriter, loc, call.getResults());
233 FunctionOpInterface funcOp,
234 LLVM::LLVMFuncOp newFuncOp) {
237 auto [wrapperType, resultStructType] =
239 cast<FunctionType>(funcOp.getFunctionType()));
243 assert(wrapperType &&
"unexpected type conversion failure");
249 auto wrapperFunc = LLVM::LLVMFuncOp::create(
250 builder, loc, llvm::formatv(
"_mlir_ciface_{0}", funcOp.getName()).str(),
251 wrapperType, LLVM::Linkage::External,
false,
252 LLVM::CConv::C,
nullptr, attributes);
256 newFuncOp.setLinkage(LLVM::Linkage::Private);
260 FunctionType type = cast<FunctionType>(funcOp.getFunctionType());
262 args.reserve(type.getNumInputs());
263 ValueRange wrapperArgsRange(newFuncOp.getArguments());
265 if (resultStructType) {
267 Type resultType = cast<LLVM::LLVMFunctionType>(wrapperType).getParamType(0);
268 Value one = LLVM::ConstantOp::create(
269 builder, loc, typeConverter.convertType(builder.
getIndexType()),
272 LLVM::AllocaOp::create(builder, loc, resultType, resultStructType, one);
278 for (
Type input : type.getInputs()) {
281 auto memRefType = dyn_cast<MemRefType>(input);
282 auto unrankedMemRefType = dyn_cast<UnrankedMemRefType>(input);
283 if (memRefType || unrankedMemRefType) {
284 numToDrop = memRefType
290 wrapperArgsRange.take_front(numToDrop))
292 builder, loc, typeConverter, unrankedMemRefType,
293 wrapperArgsRange.take_front(numToDrop));
295 auto ptrTy = LLVM::LLVMPointerType::get(builder.
getContext());
296 Value one = LLVM::ConstantOp::create(
297 builder, loc, typeConverter.convertType(builder.
getIndexType()),
299 Value allocated = LLVM::AllocaOp::create(
300 builder, loc, ptrTy, packed.
getType(), one, 0);
301 LLVM::StoreOp::create(builder, loc, packed, allocated);
304 arg = wrapperArgsRange[0];
308 wrapperArgsRange = wrapperArgsRange.drop_front(numToDrop);
310 assert(wrapperArgsRange.empty() &&
"did not map some of the arguments");
312 auto call = LLVM::CallOp::create(builder, loc, wrapperFunc, args);
314 if (resultStructType) {
316 LLVM::LoadOp::create(builder, loc, resultStructType, args.front());
317 LLVM::ReturnOp::create(builder, loc,
result);
319 LLVM::ReturnOp::create(builder, loc, call.getResults());
328 ArrayRef<std::optional<NamedAttribute>> byValRefNonPtrAttrs,
329 LLVM::LLVMFuncOp funcOp) {
331 if (funcOp.isExternal())
334 ConversionPatternRewriter::InsertionGuard guard(rewriter);
335 rewriter.setInsertionPointToStart(&funcOp.getFunctionBody().front());
337 for (
const auto &[arg, byValRefAttr] :
338 llvm::zip(funcOp.getArguments(), byValRefNonPtrAttrs)) {
344 assert(isa<LLVM::LLVMPointerType>(arg.getType()) &&
345 "Expected LLVM pointer type for argument with "
346 "`llvm.byval`/`llvm.byref` attribute");
347 Type resTy = typeConverter.convertType(
348 cast<TypeAttr>(byValRefAttr->getValue()).getValue());
350 Value valueArg = LLVM::LoadOp::create(rewriter, arg.getLoc(), resTy, arg);
351 rewriter.replaceAllUsesWith(arg, valueArg);
357 FunctionOpInterface funcOp, ConversionPatternRewriter &rewriter,
360 auto funcTy = dyn_cast<FunctionType>(funcOp.getFunctionType());
362 return rewriter.notifyMatchFailure(
363 funcOp,
"Only support FunctionOpInterface with FunctionType");
371 TypeConverter::SignatureConversion
result(funcOp.getNumArguments());
372 auto llvmType = dyn_cast_or_null<LLVM::LLVMFunctionType>(
374 funcOp, varargsAttr && varargsAttr.getValue(),
376 byValRefNonPtrAttrs));
378 return rewriter.notifyMatchFailure(funcOp,
"signature conversion failed");
382 if (funcOp->getAttrOfType<UnitAttr>(
383 LLVM::LLVMDialect::getEmitCWrapperAttrName()))
384 if (llvmType.isVarArg())
385 return funcOp.emitError(
"C interface for variadic functions is not "
389 if (failed(loweredAttrs))
390 return rewriter.notifyMatchFailure(funcOp,
391 "failed to lower func attributes");
395 if (symbolTables && symbolTableOp) {
397 symbolTable.
remove(funcOp);
400 auto newFuncOp = LLVM::LLVMFuncOp::create(rewriter, funcOp.getLoc(),
401 loweredAttrs->properties,
402 loweredAttrs->discardableAttrs);
404 if (symbolTables && symbolTableOp) {
405 auto ip = rewriter.getInsertionPoint();
407 symbolTable.
insert(newFuncOp, ip);
410 cast<FunctionOpInterface>(newFuncOp.getOperation())
411 .setVisibility(funcOp.getVisibility());
414 StringRef readnoneAttrName = LLVM::LLVMDialect::getReadnoneAttrName();
415 if (funcOp->hasAttr(readnoneAttrName)) {
416 auto memoryAttr = LLVM::MemoryEffectsAttr::get(
417 rewriter.getContext(), {LLVM::ModRefInfo::NoModRef,
418 LLVM::ModRefInfo::NoModRef,
419 LLVM::ModRefInfo::NoModRef,
420 LLVM::ModRefInfo::NoModRef,
421 LLVM::ModRefInfo::NoModRef,
422 LLVM::ModRefInfo::NoModRef});
423 newFuncOp.setMemoryEffectsAttr(memoryAttr);
428 if (ArrayAttr resAttrDicts = funcOp.getAllResultAttrs()) {
429 assert(!resAttrDicts.empty() &&
"expected array to be non-empty");
430 if (funcOp.getNumResults() == 1)
431 newFuncOp.setAllResultAttrs(resAttrDicts);
433 if (ArrayAttr argAttrDicts = funcOp.getAllArgAttrs()) {
435 cast<LLVM::LLVMFunctionType>(llvmType).getNumParams());
436 for (
unsigned i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
441 auto attrsDict = cast<DictionaryAttr>(argAttrDicts[i]);
442 convertedAttrs.reserve(attrsDict.size());
445 return TypeAttr::get(converter.convertType(
446 cast<TypeAttr>(attr.getValue()).getValue()));
448 if (attr.getName().getValue() ==
449 LLVM::LLVMDialect::getByValAttrName()) {
450 convertedAttrs.push_back(rewriter.getNamedAttr(
451 LLVM::LLVMDialect::getByValAttrName(), convert(attr)));
452 }
else if (attr.getName().getValue() ==
453 LLVM::LLVMDialect::getByRefAttrName()) {
454 convertedAttrs.push_back(rewriter.getNamedAttr(
455 LLVM::LLVMDialect::getByRefAttrName(), convert(attr)));
456 }
else if (attr.getName().getValue() ==
457 LLVM::LLVMDialect::getStructRetAttrName()) {
458 convertedAttrs.push_back(rewriter.getNamedAttr(
459 LLVM::LLVMDialect::getStructRetAttrName(), convert(attr)));
460 }
else if (attr.getName().getValue() ==
461 LLVM::LLVMDialect::getInAllocaAttrName()) {
462 convertedAttrs.push_back(rewriter.getNamedAttr(
463 LLVM::LLVMDialect::getInAllocaAttrName(), convert(attr)));
465 convertedAttrs.push_back(attr);
468 auto mapping =
result.getInputMapping(i);
469 assert(mapping &&
"unexpected deletion of function argument");
473 if (mapping->size == 1) {
474 newArgAttrs[mapping->inputNo] =
475 DictionaryAttr::get(rewriter.getContext(), convertedAttrs);
480 for (
size_t j = 0;
j < mapping->size; ++
j)
481 newArgAttrs[mapping->inputNo +
j] =
482 DictionaryAttr::get(rewriter.getContext(), {});
484 if (!newArgAttrs.empty())
485 newFuncOp.setAllArgAttrs(rewriter.getArrayAttr(newArgAttrs));
488 rewriter.inlineRegionBefore(funcOp.getFunctionBody(), newFuncOp.getBody(),
492 if (!newFuncOp.getBody().empty())
493 rewriter.applySignatureConversion(&newFuncOp.getBody().front(),
result,
503 if (funcOp->getAttrOfType<UnitAttr>(
504 LLVM::LLVMDialect::getEmitCWrapperAttrName())) {
505 if (newFuncOp.isExternal())
531 matchAndRewrite(func::FuncOp funcOp, OpAdaptor adaptor,
532 ConversionPatternRewriter &rewriter)
const override {
534 cast<FunctionOpInterface>(funcOp.getOperation()), rewriter,
535 *getTypeConverter(), symbolTables);
537 return rewriter.notifyMatchFailure(funcOp,
"Could not convert funcop");
539 rewriter.eraseOp(funcOp);
545 using ConvertOpToLLVMPattern<func::ConstantOp>::ConvertOpToLLVMPattern;
548 matchAndRewrite(func::ConstantOp op, OpAdaptor adaptor,
549 ConversionPatternRewriter &rewriter)
const override {
550 auto type = typeConverter->convertType(op.getResult().getType());
551 if (!type || !LLVM::isCompatibleType(type))
552 return rewriter.notifyMatchFailure(op,
"failed to convert result type");
555 LLVM::AddressOfOp::create(rewriter, op.getLoc(), type, op.getValue());
556 for (
const NamedAttribute &attr : op->getAttrs()) {
557 if (attr.getName().strref() ==
"value")
559 newOp->setAttr(attr.getName(), attr.getValue());
561 rewriter.replaceOp(op, newOp->getResults());
568template <
typename CallOpType>
570 using ConvertOpToLLVMPattern<CallOpType>::ConvertOpToLLVMPattern;
571 using Super = CallOpInterfaceLowering<CallOpType>;
572 using Base = ConvertOpToLLVMPattern<CallOpType>;
575 LogicalResult matchAndRewriteImpl(CallOpType callOp, Adaptor adaptor,
576 ConversionPatternRewriter &rewriter,
577 bool useBarePtrCallConv =
false)
const {
579 Type packedResult =
nullptr;
580 SmallVector<SmallVector<Type>> groupedResultTypes;
581 unsigned numResults = callOp.getNumResults();
582 auto resultTypes = llvm::to_vector<4>(callOp.getResultTypes());
583 int64_t numConvertedTypes = 0;
584 if (numResults != 0) {
585 if (!(packedResult = this->getTypeConverter()->packFunctionResults(
586 resultTypes, useBarePtrCallConv, &groupedResultTypes,
587 &numConvertedTypes)))
591 if (useBarePtrCallConv) {
592 for (
auto it : callOp->getOperands()) {
593 Type operandType = it.getType();
594 if (isa<UnrankedMemRefType>(operandType)) {
601 auto promoted = this->getTypeConverter()->promoteOperands(
602 callOp.getLoc(), callOp->getOperands(),
603 adaptor.getOperands(), rewriter, useBarePtrCallConv);
604 auto newOp = LLVM::CallOp::create(rewriter, callOp.getLoc(),
607 promoted, callOp->getAttrs());
609 newOp.getProperties().operandSegmentSizes = {
610 static_cast<int32_t
>(promoted.size()), 0};
611 newOp.getProperties().op_bundle_sizes = rewriter.getDenseI32ArrayAttr({});
620 auto getUnpackedResult = [&](
unsigned i) -> Value {
621 assert(numConvertedTypes > 0 &&
"convert op has no results");
622 if (numConvertedTypes == 1) {
623 assert(i == 0 &&
"out of bounds: converted op has only one result");
624 return newOp->getResult(0);
628 return LLVM::ExtractValueOp::create(rewriter, callOp.getLoc(),
629 newOp->getResult(0), i);
635 SmallVector<SmallVector<Value>> results;
636 results.reserve(numResults);
637 unsigned counter = 0;
638 for (
unsigned i = 0; i < numResults; ++i) {
639 SmallVector<Value> &group = results.emplace_back();
640 for (
unsigned j = 0, e = groupedResultTypes[i].size(); j < e; ++j)
641 group.push_back(getUnpackedResult(counter++));
645 for (
unsigned i = 0; i < numResults; ++i) {
646 Type origType = resultTypes[i];
647 auto memrefType = dyn_cast<MemRefType>(origType);
648 auto unrankedMemrefType = dyn_cast<UnrankedMemRefType>(origType);
649 if (useBarePtrCallConv && memrefType) {
652 assert(results[i].size() == 1 &&
"expected one converted result");
653 results[i].front() = MemRefDescriptor::fromStaticShape(
654 rewriter, callOp.getLoc(), *this->getTypeConverter(), memrefType,
657 if (unrankedMemrefType) {
658 assert(!useBarePtrCallConv &&
"unranked memref is not supported in the "
659 "bare-ptr calling convention");
660 assert(results[i].size() == 1 &&
"expected one converted result");
661 Value desc = this->copyUnrankedDescriptor(
662 rewriter, callOp.getLoc(), unrankedMemrefType, results[i].front(),
666 results[i].front() = desc;
670 rewriter.replaceOpWithMultiple(callOp, results);
675class CallOpLowering :
public CallOpInterfaceLowering<func::CallOp> {
677 explicit CallOpLowering(
const LLVMTypeConverter &typeConverter,
678 SymbolTableCollection *symbolTables =
nullptr,
679 PatternBenefit benefit = 1)
680 : CallOpInterfaceLowering<func::CallOp>(typeConverter, benefit),
681 symbolTables(symbolTables) {}
684 matchAndRewrite(func::CallOp callOp, OneToNOpAdaptor adaptor,
685 ConversionPatternRewriter &rewriter)
const override {
686 bool useBarePtrCallConv =
false;
687 if (getTypeConverter()->getOptions().useBarePtrCallConv) {
688 useBarePtrCallConv =
true;
689 }
else if (symbolTables !=
nullptr) {
692 symbolTables->lookupNearestSymbolFrom(callOp, callOp.getCalleeAttr());
702 return matchAndRewriteImpl(callOp, adaptor, rewriter, useBarePtrCallConv);
706 SymbolTableCollection *symbolTables =
nullptr;
709struct CallIndirectOpLowering
710 :
public CallOpInterfaceLowering<func::CallIndirectOp> {
714 matchAndRewrite(func::CallIndirectOp callIndirectOp, OneToNOpAdaptor adaptor,
715 ConversionPatternRewriter &rewriter)
const override {
716 return matchAndRewriteImpl(callIndirectOp, adaptor, rewriter);
720struct UnrealizedConversionCastOpLowering
722 using ConvertOpToLLVMPattern<
723 UnrealizedConversionCastOp>::ConvertOpToLLVMPattern;
726 matchAndRewrite(UnrealizedConversionCastOp op, OpAdaptor adaptor,
727 ConversionPatternRewriter &rewriter)
const override {
728 SmallVector<Type> convertedTypes;
729 if (succeeded(typeConverter->convertTypes(op.getOutputs().getTypes(),
731 convertedTypes == adaptor.getInputs().getTypes()) {
732 rewriter.replaceOp(op, adaptor.getInputs());
736 convertedTypes.clear();
737 if (succeeded(typeConverter->convertTypes(adaptor.getInputs().getTypes(),
739 convertedTypes == op.getOutputs().getType()) {
740 rewriter.replaceOp(op, adaptor.getInputs());
754 using ConvertOpToLLVMPattern<func::ReturnOp>::ConvertOpToLLVMPattern;
757 matchAndRewrite(func::ReturnOp op, OneToNOpAdaptor adaptor,
758 ConversionPatternRewriter &rewriter)
const override {
759 Location loc = op.getLoc();
760 SmallVector<Value, 4> updatedOperands;
762 auto funcOp = op->getParentOfType<LLVM::LLVMFuncOp>();
763 bool useBarePtrCallConv =
766 for (
auto [oldOperand, newOperands] :
767 llvm::zip_equal(op->getOperands(), adaptor.getOperands())) {
768 Type oldTy = oldOperand.getType();
769 if (
auto memRefType = dyn_cast<MemRefType>(oldTy)) {
770 assert(newOperands.size() == 1 &&
"expected one converted result");
771 if (useBarePtrCallConv &&
772 getTypeConverter()->canConvertToBarePtr(memRefType)) {
775 MemRefDescriptor memrefDesc(newOperands.front());
776 updatedOperands.push_back(memrefDesc.allocatedPtr(rewriter, loc));
779 }
else if (
auto unrankedMemRefType =
780 dyn_cast<UnrankedMemRefType>(oldTy)) {
781 assert(newOperands.size() == 1 &&
"expected one converted result");
782 if (useBarePtrCallConv) {
788 copyUnrankedDescriptor(rewriter, loc, unrankedMemRefType,
789 newOperands.front(),
true);
792 updatedOperands.push_back(updatedDesc);
796 llvm::append_range(updatedOperands, newOperands);
800 if (updatedOperands.size() <= 1) {
801 rewriter.replaceOpWithNewOp<LLVM::ReturnOp>(
802 op,
TypeRange(), updatedOperands, op->getAttrs());
808 auto packedType = getTypeConverter()->packFunctionResults(
809 op.getOperandTypes(), useBarePtrCallConv);
811 return rewriter.notifyMatchFailure(op,
"could not convert result types");
814 Value packed = LLVM::PoisonOp::create(rewriter, loc, packedType);
815 for (
auto [idx, operand] : llvm::enumerate(updatedOperands)) {
816 packed = LLVM::InsertValueOp::create(rewriter, loc, packed, operand, idx);
818 rewriter.replaceOpWithNewOp<LLVM::ReturnOp>(op,
TypeRange(), packed,
828 patterns.
add<FuncOpConversion>(converter, symbolTables);
835 patterns.
add<CallIndirectOpLowering>(converter);
836 patterns.
add<CallOpLowering>(converter, symbolTables);
837 patterns.
add<ConstantOpLowering>(converter);
838 patterns.
add<ReturnOpLowering>(converter);
843struct ConvertFuncToLLVMPass
844 :
public impl::ConvertFuncToLLVMPassBase<ConvertFuncToLLVMPass> {
848 void runOnOperation()
override {
849 ModuleOp m = getOperation();
850 StringRef dataLayout;
851 auto dataLayoutAttr = dyn_cast_or_null<StringAttr>(
852 m->getAttr(LLVM::LLVMDialect::getDataLayoutAttrName()));
854 dataLayout = dataLayoutAttr.getValue();
856 if (failed(LLVM::LLVMDialect::verifyDataLayoutString(
857 dataLayout, [
this](
const Twine &message) {
858 getOperation().emitError() << message.str();
864 const auto &dataLayoutAnalysis = getAnalysis<DataLayoutAnalysis>();
867 dataLayoutAnalysis.getAtOrAbove(m));
868 options.useBarePtrCallConv = useBarePtrCallConv;
870 options.overrideIndexBitwidth(indexBitwidth);
871 options.dataLayout = llvm::DataLayout(dataLayout);
874 &dataLayoutAnalysis);
877 SymbolTableCollection symbolTables;
883 if (
failed(applyPartialConversion(m,
target, std::move(patterns))))
888struct SetLLVMModuleDataLayoutPass
889 :
public impl::SetLLVMModuleDataLayoutPassBase<
890 SetLLVMModuleDataLayoutPass> {
894 void runOnOperation()
override {
895 if (
failed(LLVM::LLVMDialect::verifyDataLayoutString(
896 this->dataLayout, [
this](
const Twine &message) {
897 getOperation().emitError() << message.str();
902 ModuleOp m = getOperation();
903 m->setAttr(LLVM::LLVMDialect::getDataLayoutAttrName(),
904 StringAttr::get(m.getContext(), this->dataLayout));
915struct FuncToLLVMDialectInterface :
public ConvertToLLVMPatternInterface {
916 FuncToLLVMDialectInterface(Dialect *dialect)
917 : ConvertToLLVMPatternInterface(dialect) {}
920 void populateConvertToLLVMConversionPatterns(
921 ConversionTarget &
target, LLVMTypeConverter &typeConverter,
922 RewritePatternSet &patterns)
const final {
930 dialect->addInterfaces<FuncToLLVMDialectInterface>();
static void restoreByValRefArgumentType(ConversionPatternRewriter &rewriter, const LLVMTypeConverter &typeConverter, ArrayRef< std::optional< NamedAttribute > > byValRefNonPtrAttrs, LLVM::LLVMFuncOp funcOp)
Inserts llvm.load ops in the function body to restore the expected pointee value from llvm....
static void propagateArgResAttrs(OpBuilder &builder, bool resultStructType, FunctionOpInterface funcOp, LLVM::LLVMFuncOp wrapperFuncOp)
Propagate argument/results attributes.
static bool isDiscardableAttr(StringRef name)
static constexpr StringRef barePtrAttrName
static constexpr StringRef varargsAttrName
static constexpr StringRef linkageAttrName
static void filterFuncAttributes(FunctionOpInterface func, SmallVectorImpl< NamedAttribute > &result)
Only retain those attributes that are not constructed by LLVMFuncOp::build.
static bool shouldUseBarePtrCallConv(Operation *op, const LLVMTypeConverter *typeConverter)
Return true if the op should use bare pointer calling convention.
static void wrapExternalFunction(OpBuilder &builder, Location loc, const LLVMTypeConverter &typeConverter, FunctionOpInterface funcOp, LLVM::LLVMFuncOp newFuncOp)
Creates an auxiliary function with pointer-to-memref-descriptor-struct arguments instead of unpacked ...
static void buildLLVMFuncProperties(PatternRewriter &rewriter, FunctionOpInterface srcFunc, Type llvmFuncType, LLVM::LLVMFuncOp::Properties &props)
static FailureOr< LoweredFuncAttrs > lowerFuncAttributes(FunctionOpInterface func)
Lower discardable function attributes on func.func to attributes expected by llvm....
static void wrapForExternalCallers(OpBuilder &rewriter, Location loc, const LLVMTypeConverter &typeConverter, FunctionOpInterface funcOp, LLVM::LLVMFuncOp newFuncOp)
Creates an auxiliary function with pointer-to-memref-descriptor-struct arguments instead of unpacked ...
static llvm::ManagedStatic< PassManagerOptions > options
Special case of IntegerAttr to represent boolean integers, i.e., signless i1 integers.
IntegerAttr getIntegerAttr(Type type, int64_t value)
StringAttr getStringAttr(const Twine &bytes)
MLIRContext * getContext() const
DictionaryAttr getDictionaryAttr(ArrayRef< NamedAttribute > value)
Utility class for operation conversions targeting the LLVM dialect that match exactly one source oper...
typename SourceOp::template GenericAdaptor< ArrayRef< ValueRange > > OneToNOpAdaptor
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
bool addExtension(TypeID extensionID, std::unique_ptr< DialectExtensionBase > extension)
Add the given extension to the registry.
Conversion from types to the LLVM IR dialect.
Type convertFunctionSignature(FunctionType funcTy, bool isVariadic, bool useBarePtrCallConv, SignatureConversion &result) const
Convert a function type.
const LowerToLLVMOptions & getOptions() const
std::pair< LLVM::LLVMFunctionType, LLVM::LLVMStructType > convertFunctionTypeCWrapper(FunctionType type) const
Converts the function type to a C-compatible format, in particular using pointers to memref descripto...
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
static void unpack(OpBuilder &builder, Location loc, Value packed, MemRefType type, SmallVectorImpl< Value > &results)
Builds IR extracting individual elements of a MemRef descriptor structure and returning them as resul...
static unsigned getNumUnpackedValues(MemRefType type)
Returns the number of non-aggregate values that would be produced by unpack.
static Value pack(OpBuilder &builder, Location loc, const LLVMTypeConverter &converter, MemRefType type, ValueRange values)
Builds IR populating a MemRef descriptor structure from a list of individual values composing that de...
NamedAttrList is array of NamedAttributes that tracks whether it is sorted and does some basic work t...
DictionaryAttr getDictionary(MLIRContext *context) const
Return a dictionary attribute for the underlying dictionary.
void push_back(NamedAttribute newAttribute)
Add an attribute with the specified name.
Attribute set(StringAttr name, Attribute value)
If the an attribute exists with the specified name, change it to the new value.
NamedAttribute represents a combination of a name and an Attribute value.
RAII guard to reset the insertion point of the builder when destroyed.
This class helps build Operations.
void setInsertionPointToStart(Block *block)
Sets the insertion point to the start of the specified block.
A trait used to provide symbol table functionalities to a region operation.
Operation is the basic unit of execution within MLIR.
bool hasAttr(StringAttr name)
Return true if the operation has an attribute with the provided name, false otherwise.
Operation * getParentWithTrait()
Returns the closest surrounding parent operation with trait Trait.
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
This class represents a collection of SymbolTables.
virtual SymbolTable & getSymbolTable(Operation *op)
Lookup, or create, a symbol table for an operation.
This class allows for representing and managing the symbol table used by operations with the 'SymbolT...
static Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
StringAttr insert(Operation *symbol, Block::iterator insertPt={})
Insert a new symbol into the table, and rename it as necessary to avoid collisions.
void remove(Operation *op)
Remove the given symbol from the table, without deleting it.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
static Value pack(OpBuilder &builder, Location loc, const LLVMTypeConverter &converter, UnrankedMemRefType type, ValueRange values)
Builds IR populating an unranked MemRef descriptor structure from a list of individual constituent va...
static void unpack(OpBuilder &builder, Location loc, Value packed, SmallVectorImpl< Value > &results)
Builds IR extracting individual elements that compose an unranked memref descriptor and returns them ...
static unsigned getNumUnpackedValues()
Returns the number of non-aggregate values that would be produced by unpack.
This class provides an abstraction over the different types of ranges over Values.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
Include the generated interface declarations.
static constexpr unsigned kDeriveIndexBitwidthFromDataLayout
Value to pass as bitwidth for the index type when the converter is expected to derive the bitwidth fr...
void registerConvertFuncToLLVMInterface(DialectRegistry ®istry)
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
void populateFuncToLLVMConversionPatterns(const LLVMTypeConverter &converter, RewritePatternSet &patterns, SymbolTableCollection *symbolTables=nullptr)
Collect the patterns to convert from the Func dialect to LLVM.
void populateFuncToLLVMFuncOpConversionPattern(const LLVMTypeConverter &converter, RewritePatternSet &patterns, SymbolTableCollection *symbolTables=nullptr)
Collect the default pattern to convert a FuncOp to the LLVM dialect.
FailureOr< LLVM::LLVMFuncOp > convertFuncOpToLLVMFuncOp(FunctionOpInterface funcOp, ConversionPatternRewriter &rewriter, const LLVMTypeConverter &converter, SymbolTableCollection *symbolTables=nullptr)
Convert input FunctionOpInterface operation to LLVMFuncOp by using the provided LLVMTypeConverter.
Add custom lowered funcOp to llvm.func attributes here.
NamedAttrList discardableAttrs
LLVM::LLVMFuncOp::Properties properties
Eliminates variable at the specified position using Fourier-Motzkin variable elimination.