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 bool useBarePtrCallConv, TypeConverter::SignatureConversion &
result,
360 auto llvmType = dyn_cast_or_null<LLVM::LLVMFunctionType>(
362 funcOp, varargsAttr && varargsAttr.getValue(), useBarePtrCallConv,
363 result, byValRefNonPtrAttrs));
370 ConversionPatternRewriter &rewriter,
371 LLVM::LLVMFunctionType llvmType,
375 if (symbolTables && symbolTableOp) {
377 symbolTable.
remove(funcOp);
380 auto newFuncOp = LLVM::LLVMFuncOp::create(rewriter, funcOp.getLoc(),
384 if (symbolTables && symbolTableOp) {
385 auto ip = rewriter.getInsertionPoint();
387 symbolTable.
insert(newFuncOp, ip);
390 cast<FunctionOpInterface>(newFuncOp.getOperation())
391 .setVisibility(funcOp.getVisibility());
394 if (funcOp->hasAttr(LLVM::LLVMDialect::getReadnoneAttrName())) {
395 auto memoryAttr = LLVM::MemoryEffectsAttr::get(
396 rewriter.getContext(), {LLVM::ModRefInfo::NoModRef,
397 LLVM::ModRefInfo::NoModRef,
398 LLVM::ModRefInfo::NoModRef,
399 LLVM::ModRefInfo::NoModRef,
400 LLVM::ModRefInfo::NoModRef,
401 LLVM::ModRefInfo::NoModRef});
402 newFuncOp.setMemoryEffectsAttr(memoryAttr);
410 ConversionPatternRewriter &rewriter,
413 convertedAttrs.reserve(attrsDict.size());
416 return TypeAttr::get(
417 converter.convertType(cast<TypeAttr>(attr.getValue()).getValue()));
419 if (attr.getName().getValue() == LLVM::LLVMDialect::getByValAttrName()) {
420 convertedAttrs.push_back(rewriter.getNamedAttr(
421 LLVM::LLVMDialect::getByValAttrName(), convert(attr)));
422 }
else if (attr.getName().getValue() ==
423 LLVM::LLVMDialect::getByRefAttrName()) {
424 convertedAttrs.push_back(rewriter.getNamedAttr(
425 LLVM::LLVMDialect::getByRefAttrName(), convert(attr)));
426 }
else if (attr.getName().getValue() ==
427 LLVM::LLVMDialect::getStructRetAttrName()) {
428 convertedAttrs.push_back(rewriter.getNamedAttr(
429 LLVM::LLVMDialect::getStructRetAttrName(), convert(attr)));
430 }
else if (attr.getName().getValue() ==
431 LLVM::LLVMDialect::getInAllocaAttrName()) {
432 convertedAttrs.push_back(rewriter.getNamedAttr(
433 LLVM::LLVMDialect::getInAllocaAttrName(), convert(attr)));
435 convertedAttrs.push_back(attr);
438 return convertedAttrs;
442 FunctionOpInterface funcOp, ConversionPatternRewriter &rewriter,
444 LLVM::LLVMFunctionType llvmType, LLVM::LLVMFuncOp newFuncOp) {
447 if (
ArrayAttr resAttrDicts = funcOp.getAllResultAttrs()) {
448 assert(!resAttrDicts.empty() &&
"expected array to be non-empty");
449 if (funcOp.getNumResults() == 1)
450 newFuncOp.setAllResultAttrs(resAttrDicts);
452 if (
ArrayAttr argAttrDicts = funcOp.getAllArgAttrs()) {
454 for (
unsigned i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
458 auto attrsDict = cast<DictionaryAttr>(argAttrDicts[i]);
461 auto mapping = sig.getInputMapping(i);
462 assert(mapping &&
"unexpected deletion of function argument");
466 if (mapping->size == 1) {
467 newArgAttrs[mapping->inputNo] =
468 DictionaryAttr::get(rewriter.getContext(), convertedAttrs);
473 for (
size_t j = 0;
j < mapping->size; ++
j)
474 newArgAttrs[mapping->inputNo +
j] =
475 DictionaryAttr::get(rewriter.getContext(), {});
477 if (!newArgAttrs.empty())
478 newFuncOp.setAllArgAttrs(rewriter.getArrayAttr(newArgAttrs));
483 ConversionPatternRewriter &rewriter,
485 LLVM::LLVMFuncOp newFuncOp) {
486 if (newFuncOp.isExternal())
505 FunctionOpInterface funcOp, ConversionPatternRewriter &rewriter,
509 auto funcTy = dyn_cast<FunctionType>(funcOp.getFunctionType());
511 return rewriter.notifyMatchFailure(
512 funcOp,
"Only support FunctionOpInterface with FunctionType");
521 TypeConverter::SignatureConversion
result(funcOp.getNumArguments());
523 funcOp, converter, useBarePtrCallConv,
result, byValRefNonPtrAttrs);
524 if (failed(llvmType))
525 return rewriter.notifyMatchFailure(funcOp,
"signature conversion failed");
528 bool emitCWrapper = funcOp->hasAttrOfType<UnitAttr>(
529 LLVM::LLVMDialect::getEmitCWrapperAttrName());
530 if (!useBarePtrCallConv && emitCWrapper && llvmType->isVarArg())
531 return funcOp.emitError(
"C interface for variadic functions is not "
536 if (failed(loweredAttrs))
537 return rewriter.notifyMatchFailure(funcOp,
538 "failed to lower func attributes");
541 auto newFuncOp =
createLLVMFuncOp(funcOp, rewriter, *llvmType, *loweredAttrs,
549 rewriter.inlineRegionBefore(funcOp.getFunctionBody(), newFuncOp.getBody(),
553 if (!newFuncOp.getBody().empty())
554 rewriter.applySignatureConversion(&newFuncOp.getBody().front(),
result,
565 if (!useBarePtrCallConv && emitCWrapper)
585 matchAndRewrite(func::FuncOp funcOp, OpAdaptor adaptor,
586 ConversionPatternRewriter &rewriter)
const override {
588 cast<FunctionOpInterface>(funcOp.getOperation()), rewriter,
589 *getTypeConverter(), symbolTables);
591 return rewriter.notifyMatchFailure(funcOp,
"Could not convert funcop");
593 rewriter.eraseOp(funcOp);
599 using ConvertOpToLLVMPattern<func::ConstantOp>::ConvertOpToLLVMPattern;
602 matchAndRewrite(func::ConstantOp op, OpAdaptor adaptor,
603 ConversionPatternRewriter &rewriter)
const override {
604 auto type = typeConverter->convertType(op.getResult().getType());
605 if (!type || !LLVM::isCompatibleType(type))
606 return rewriter.notifyMatchFailure(op,
"failed to convert result type");
609 LLVM::AddressOfOp::create(rewriter, op.getLoc(), type, op.getValue());
610 for (
const NamedAttribute &attr : op->getAttrs()) {
611 if (attr.getName().strref() ==
"value")
613 newOp->setAttr(attr.getName(), attr.getValue());
615 rewriter.replaceOp(op, newOp->getResults());
622template <
typename CallOpType>
624 using ConvertOpToLLVMPattern<CallOpType>::ConvertOpToLLVMPattern;
625 using Super = CallOpInterfaceLowering<CallOpType>;
626 using Base = ConvertOpToLLVMPattern<CallOpType>;
629 LogicalResult matchAndRewriteImpl(CallOpType callOp, Adaptor adaptor,
630 ConversionPatternRewriter &rewriter,
631 bool useBarePtrCallConv =
false)
const {
633 Type packedResult =
nullptr;
634 SmallVector<SmallVector<Type>> groupedResultTypes;
635 unsigned numResults = callOp.getNumResults();
636 auto resultTypes = llvm::to_vector<4>(callOp.getResultTypes());
637 int64_t numConvertedTypes = 0;
638 if (numResults != 0) {
639 if (!(packedResult = this->getTypeConverter()->packFunctionResults(
640 resultTypes, useBarePtrCallConv, &groupedResultTypes,
641 &numConvertedTypes)))
645 if (useBarePtrCallConv) {
646 for (
auto it : callOp->getOperands()) {
647 Type operandType = it.getType();
648 if (isa<UnrankedMemRefType>(operandType)) {
655 auto promoted = this->getTypeConverter()->promoteOperands(
656 callOp.getLoc(), callOp->getOperands(),
657 adaptor.getOperands(), rewriter, useBarePtrCallConv);
658 auto newOp = LLVM::CallOp::create(rewriter, callOp.getLoc(),
661 promoted, callOp->getAttrs());
663 newOp.getProperties().operandSegmentSizes = {
664 static_cast<int32_t
>(promoted.size()), 0};
665 newOp.getProperties().op_bundle_sizes = rewriter.getDenseI32ArrayAttr({});
674 auto getUnpackedResult = [&](
unsigned i) -> Value {
675 assert(numConvertedTypes > 0 &&
"convert op has no results");
676 if (numConvertedTypes == 1) {
677 assert(i == 0 &&
"out of bounds: converted op has only one result");
678 return newOp->getResult(0);
682 return LLVM::ExtractValueOp::create(rewriter, callOp.getLoc(),
683 newOp->getResult(0), i);
689 SmallVector<SmallVector<Value>> results;
690 results.reserve(numResults);
691 unsigned counter = 0;
692 for (
unsigned i = 0; i < numResults; ++i) {
693 SmallVector<Value> &group = results.emplace_back();
694 for (
unsigned j = 0, e = groupedResultTypes[i].size(); j < e; ++j)
695 group.push_back(getUnpackedResult(counter++));
699 for (
unsigned i = 0; i < numResults; ++i) {
700 Type origType = resultTypes[i];
701 auto memrefType = dyn_cast<MemRefType>(origType);
702 auto unrankedMemrefType = dyn_cast<UnrankedMemRefType>(origType);
703 if (useBarePtrCallConv && memrefType) {
706 assert(results[i].size() == 1 &&
"expected one converted result");
707 results[i].front() = MemRefDescriptor::fromStaticShape(
708 rewriter, callOp.getLoc(), *this->getTypeConverter(), memrefType,
711 if (unrankedMemrefType) {
712 assert(!useBarePtrCallConv &&
"unranked memref is not supported in the "
713 "bare-ptr calling convention");
714 assert(results[i].size() == 1 &&
"expected one converted result");
715 Value desc = this->copyUnrankedDescriptor(
716 rewriter, callOp.getLoc(), unrankedMemrefType, results[i].front(),
720 results[i].front() = desc;
724 rewriter.replaceOpWithMultiple(callOp, results);
729class CallOpLowering :
public CallOpInterfaceLowering<func::CallOp> {
731 explicit CallOpLowering(
const LLVMTypeConverter &typeConverter,
732 SymbolTableCollection *symbolTables =
nullptr,
733 PatternBenefit benefit = 1)
734 : CallOpInterfaceLowering<func::CallOp>(typeConverter, benefit),
735 symbolTables(symbolTables) {}
738 matchAndRewrite(func::CallOp callOp, OneToNOpAdaptor adaptor,
739 ConversionPatternRewriter &rewriter)
const override {
740 bool useBarePtrCallConv =
false;
741 if (getTypeConverter()->getOptions().useBarePtrCallConv) {
742 useBarePtrCallConv =
true;
743 }
else if (symbolTables !=
nullptr) {
746 symbolTables->lookupNearestSymbolFrom(callOp, callOp.getCalleeAttr());
756 return matchAndRewriteImpl(callOp, adaptor, rewriter, useBarePtrCallConv);
760 SymbolTableCollection *symbolTables =
nullptr;
763struct CallIndirectOpLowering
764 :
public CallOpInterfaceLowering<func::CallIndirectOp> {
768 matchAndRewrite(func::CallIndirectOp callIndirectOp, OneToNOpAdaptor adaptor,
769 ConversionPatternRewriter &rewriter)
const override {
770 return matchAndRewriteImpl(callIndirectOp, adaptor, rewriter);
774struct UnrealizedConversionCastOpLowering
776 using ConvertOpToLLVMPattern<
777 UnrealizedConversionCastOp>::ConvertOpToLLVMPattern;
780 matchAndRewrite(UnrealizedConversionCastOp op, OpAdaptor adaptor,
781 ConversionPatternRewriter &rewriter)
const override {
782 SmallVector<Type> convertedTypes;
783 if (succeeded(typeConverter->convertTypes(op.getOutputs().getTypes(),
785 convertedTypes == adaptor.getInputs().getTypes()) {
786 rewriter.replaceOp(op, adaptor.getInputs());
790 convertedTypes.clear();
791 if (succeeded(typeConverter->convertTypes(adaptor.getInputs().getTypes(),
793 convertedTypes == op.getOutputs().getType()) {
794 rewriter.replaceOp(op, adaptor.getInputs());
808 using ConvertOpToLLVMPattern<func::ReturnOp>::ConvertOpToLLVMPattern;
811 matchAndRewrite(func::ReturnOp op, OneToNOpAdaptor adaptor,
812 ConversionPatternRewriter &rewriter)
const override {
813 Location loc = op.getLoc();
814 SmallVector<Value, 4> updatedOperands;
816 auto funcOp = op->getParentOfType<LLVM::LLVMFuncOp>();
817 bool useBarePtrCallConv =
820 for (
auto [oldOperand, newOperands] :
821 llvm::zip_equal(op->getOperands(), adaptor.getOperands())) {
822 Type oldTy = oldOperand.getType();
823 if (
auto memRefType = dyn_cast<MemRefType>(oldTy)) {
824 assert(newOperands.size() == 1 &&
"expected one converted result");
825 if (useBarePtrCallConv &&
826 getTypeConverter()->canConvertToBarePtr(memRefType)) {
829 MemRefDescriptor memrefDesc(newOperands.front());
830 updatedOperands.push_back(memrefDesc.allocatedPtr(rewriter, loc));
833 }
else if (
auto unrankedMemRefType =
834 dyn_cast<UnrankedMemRefType>(oldTy)) {
835 assert(newOperands.size() == 1 &&
"expected one converted result");
836 if (useBarePtrCallConv) {
842 copyUnrankedDescriptor(rewriter, loc, unrankedMemRefType,
843 newOperands.front(),
true);
846 updatedOperands.push_back(updatedDesc);
850 llvm::append_range(updatedOperands, newOperands);
854 if (updatedOperands.size() <= 1) {
855 rewriter.replaceOpWithNewOp<LLVM::ReturnOp>(
856 op,
TypeRange(), updatedOperands, op->getAttrs());
862 auto packedType = getTypeConverter()->packFunctionResults(
863 op.getOperandTypes(), useBarePtrCallConv);
865 return rewriter.notifyMatchFailure(op,
"could not convert result types");
868 Value packed = LLVM::PoisonOp::create(rewriter, loc, packedType);
869 for (
auto [idx, operand] : llvm::enumerate(updatedOperands)) {
870 packed = LLVM::InsertValueOp::create(rewriter, loc, packed, operand, idx);
872 rewriter.replaceOpWithNewOp<LLVM::ReturnOp>(op,
TypeRange(), packed,
882 patterns.
add<FuncOpConversion>(converter, symbolTables);
889 patterns.
add<CallIndirectOpLowering>(converter);
890 patterns.
add<CallOpLowering>(converter, symbolTables);
891 patterns.
add<ConstantOpLowering>(converter);
892 patterns.
add<ReturnOpLowering>(converter);
897struct ConvertFuncToLLVMPass
898 :
public impl::ConvertFuncToLLVMPassBase<ConvertFuncToLLVMPass> {
902 void runOnOperation()
override {
903 ModuleOp m = getOperation();
904 StringRef dataLayout;
905 auto dataLayoutAttr = dyn_cast_or_null<StringAttr>(
906 m->getAttr(LLVM::LLVMDialect::getDataLayoutAttrName()));
908 dataLayout = dataLayoutAttr.getValue();
910 if (failed(LLVM::LLVMDialect::verifyDataLayoutString(
911 dataLayout, [
this](
const Twine &message) {
912 getOperation().emitError() << message.str();
918 const auto &dataLayoutAnalysis = getAnalysis<DataLayoutAnalysis>();
921 dataLayoutAnalysis.getAtOrAbove(m));
922 options.useBarePtrCallConv = useBarePtrCallConv;
924 options.overrideIndexBitwidth(indexBitwidth);
925 options.dataLayout = llvm::DataLayout(dataLayout);
928 &dataLayoutAnalysis);
931 SymbolTableCollection symbolTables;
937 if (
failed(applyPartialConversion(m,
target, std::move(patterns))))
942struct SetLLVMModuleDataLayoutPass
943 :
public impl::SetLLVMModuleDataLayoutPassBase<
944 SetLLVMModuleDataLayoutPass> {
948 void runOnOperation()
override {
949 if (
failed(LLVM::LLVMDialect::verifyDataLayoutString(
950 this->dataLayout, [
this](
const Twine &message) {
951 getOperation().emitError() << message.str();
956 ModuleOp m = getOperation();
957 m->setAttr(LLVM::LLVMDialect::getDataLayoutAttrName(),
958 StringAttr::get(m.getContext(), this->dataLayout));
969struct FuncToLLVMDialectInterface :
public ConvertToLLVMPatternInterface {
970 FuncToLLVMDialectInterface(Dialect *dialect)
971 : ConvertToLLVMPatternInterface(dialect) {}
974 void populateConvertToLLVMConversionPatterns(
975 ConversionTarget &
target, LLVMTypeConverter &typeConverter,
976 RewritePatternSet &patterns)
const final {
984 dialect->addInterfaces<FuncToLLVMDialectInterface>();
static FailureOr< LLVM::LLVMFunctionType > convertFuncSignature(FunctionOpInterface funcOp, const LLVMTypeConverter &converter, bool useBarePtrCallConv, TypeConverter::SignatureConversion &result, SmallVectorImpl< std::optional< NamedAttribute > > &byValRefNonPtrAttrs)
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 SmallVector< NamedAttribute > convertArgumentAttributes(DictionaryAttr attrsDict, ConversionPatternRewriter &rewriter, const LLVMTypeConverter &converter)
static bool isDiscardableAttr(StringRef name)
static LLVM::LLVMFuncOp createLLVMFuncOp(FunctionOpInterface funcOp, ConversionPatternRewriter &rewriter, LLVM::LLVMFunctionType llvmType, LoweredFuncAttrs &loweredAttrs, SymbolTableCollection *symbolTables)
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 void propagateFunctionArgResAttrs(FunctionOpInterface funcOp, ConversionPatternRewriter &rewriter, const LLVMTypeConverter &converter, TypeConverter::SignatureConversion &sig, LLVM::LLVMFunctionType llvmType, LLVM::LLVMFuncOp newFuncOp)
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 void wrapWithCInterface(FunctionOpInterface funcOp, ConversionPatternRewriter &rewriter, const LLVMTypeConverter &converter, LLVM::LLVMFuncOp newFuncOp)
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.