37#include "llvm/ADT/SmallVector.h"
38#include "llvm/IR/Type.h"
39#include "llvm/Support/DebugLog.h"
40#include "llvm/Support/FormatVariadic.h"
44#define GEN_PASS_DEF_CONVERTFUNCTOLLVMPASS
45#define GEN_PASS_DEF_SETLLVMMODULEDATALAYOUTPASS
46#include "mlir/Conversion/Passes.h.inc"
51#define PASS_NAME "convert-func-to-llvm"
52#define DEBUG_TYPE PASS_NAME
67 name == LLVM::LLVMDialect::getReadnoneAttrName();
75 func->getDiscardableAttrDictionary().getValue()) {
84 FunctionOpInterface funcOp,
85 LLVM::LLVMFuncOp wrapperFuncOp) {
86 auto argAttrs = funcOp.getAllArgAttrs();
87 if (!resultStructType) {
88 if (
auto resAttrs = funcOp.getAllResultAttrs())
89 wrapperFuncOp.setAllResultAttrs(resAttrs);
91 wrapperFuncOp.setAllArgAttrs(argAttrs);
98 argAttributes.append(argAttrs.begin(), argAttrs.end());
99 wrapperFuncOp.setAllArgAttrs(argAttributes);
102 cast<FunctionOpInterface>(wrapperFuncOp.getOperation())
103 .setVisibility(funcOp.getVisibility());
116 FunctionOpInterface funcOp,
117 LLVM::LLVMFuncOp newFuncOp) {
118 auto type = cast<FunctionType>(funcOp.getFunctionType());
119 auto [wrapperFuncType, resultStructType] =
125 auto wrapperFuncOp = LLVM::LLVMFuncOp::create(
126 rewriter, loc, llvm::formatv(
"_mlir_ciface_{0}", funcOp.getName()).str(),
127 wrapperFuncType, LLVM::Linkage::External,
false,
128 LLVM::CConv::C,
nullptr, attributes);
135 size_t argOffset = resultStructType ? 1 : 0;
136 for (
auto [
index, argType] : llvm::enumerate(type.getInputs())) {
137 Value arg = wrapperFuncOp.getArgument(
index + argOffset);
138 if (
auto memrefType = dyn_cast<MemRefType>(argType)) {
139 Value loaded = LLVM::LoadOp::create(
140 rewriter, loc, typeConverter.convertType(memrefType), arg);
144 if (isa<UnrankedMemRefType>(argType)) {
145 Value loaded = LLVM::LoadOp::create(
146 rewriter, loc, typeConverter.convertType(argType), arg);
154 auto call = LLVM::CallOp::create(rewriter, loc, newFuncOp, args);
156 if (resultStructType) {
157 LLVM::StoreOp::create(rewriter, loc, call.getResult(),
158 wrapperFuncOp.getArgument(0));
159 LLVM::ReturnOp::create(rewriter, loc,
ValueRange{});
161 LLVM::ReturnOp::create(rewriter, loc, call.getResults());
176 FunctionOpInterface funcOp,
177 LLVM::LLVMFuncOp newFuncOp) {
180 auto [wrapperType, resultStructType] =
182 cast<FunctionType>(funcOp.getFunctionType()));
186 assert(wrapperType &&
"unexpected type conversion failure");
192 auto wrapperFunc = LLVM::LLVMFuncOp::create(
193 builder, loc, llvm::formatv(
"_mlir_ciface_{0}", funcOp.getName()).str(),
194 wrapperType, LLVM::Linkage::External,
false,
195 LLVM::CConv::C,
nullptr, attributes);
199 newFuncOp.setLinkage(LLVM::Linkage::Private);
203 FunctionType type = cast<FunctionType>(funcOp.getFunctionType());
205 args.reserve(type.getNumInputs());
206 ValueRange wrapperArgsRange(newFuncOp.getArguments());
208 if (resultStructType) {
210 Type resultType = cast<LLVM::LLVMFunctionType>(wrapperType).getParamType(0);
212 Value one = LLVM::ConstantOp::create(builder, loc, indexType,
215 LLVM::AllocaOp::create(builder, loc, resultType, resultStructType, one);
221 for (
Type input : type.getInputs()) {
224 auto memRefType = dyn_cast<MemRefType>(input);
225 auto unrankedMemRefType = dyn_cast<UnrankedMemRefType>(input);
226 if (memRefType || unrankedMemRefType) {
227 numToDrop = memRefType
233 wrapperArgsRange.take_front(numToDrop))
235 builder, loc, typeConverter, unrankedMemRefType,
236 wrapperArgsRange.take_front(numToDrop));
238 auto ptrTy = LLVM::LLVMPointerType::get(builder.
getContext());
240 Value one = LLVM::ConstantOp::create(
242 Value allocated = LLVM::AllocaOp::create(
243 builder, loc, ptrTy, packed.
getType(), one, 0);
244 LLVM::StoreOp::create(builder, loc, packed, allocated);
247 arg = wrapperArgsRange[0];
251 wrapperArgsRange = wrapperArgsRange.drop_front(numToDrop);
253 assert(wrapperArgsRange.empty() &&
"did not map some of the arguments");
255 auto call = LLVM::CallOp::create(builder, loc, wrapperFunc, args);
257 if (resultStructType) {
259 LLVM::LoadOp::create(builder, loc, resultStructType, args.front());
260 LLVM::ReturnOp::create(builder, loc,
result);
262 LLVM::ReturnOp::create(builder, loc, call.getResults());
271 ArrayRef<std::optional<NamedAttribute>> byValRefNonPtrAttrs,
272 LLVM::LLVMFuncOp funcOp) {
274 if (funcOp.isExternal())
277 ConversionPatternRewriter::InsertionGuard guard(rewriter);
278 rewriter.setInsertionPointToStart(&funcOp.getFunctionBody().front());
280 for (
const auto &[arg, byValRefAttr] :
281 llvm::zip(funcOp.getArguments(), byValRefNonPtrAttrs)) {
287 assert(isa<LLVM::LLVMPointerType>(arg.getType()) &&
288 "Expected LLVM pointer type for argument with "
289 "`llvm.byval`/`llvm.byref` attribute");
290 Type resTy = typeConverter.convertType(
291 cast<TypeAttr>(byValRefAttr->getValue()).getValue());
293 Value valueArg = LLVM::LoadOp::create(rewriter, arg.getLoc(), resTy, arg);
294 rewriter.replaceAllUsesWith(arg, valueArg);
300 bool useBarePtrCallConv, TypeConverter::SignatureConversion &
result,
304 auto llvmType = dyn_cast_or_null<LLVM::LLVMFunctionType>(
306 funcOp, varargsAttr && varargsAttr.getValue(), useBarePtrCallConv,
307 result, byValRefNonPtrAttrs));
314 ConversionPatternRewriter &rewriter,
315 LLVM::LLVMFunctionType llvmType,
319 if (symbolTables && symbolTableOp) {
321 symbolTable.
remove(funcOp);
324 LLVM::CConvAttr::get(rewriter.getContext(), LLVM::CConv::C));
325 auto newFuncOp = LLVM::LLVMFuncOp::create(rewriter, funcOp.getLoc(),
329 if (symbolTables && symbolTableOp) {
330 auto ip = rewriter.getInsertionPoint();
332 symbolTable.
insert(newFuncOp, ip);
335 cast<FunctionOpInterface>(newFuncOp.getOperation())
336 .setVisibility(funcOp.getVisibility());
339 if (funcOp->hasDiscardableAttr(LLVM::LLVMDialect::getReadnoneAttrName())) {
340 auto memoryAttr = LLVM::MemoryEffectsAttr::get(
341 rewriter.getContext(), {LLVM::ModRefInfo::NoModRef,
342 LLVM::ModRefInfo::NoModRef,
343 LLVM::ModRefInfo::NoModRef,
344 LLVM::ModRefInfo::NoModRef,
345 LLVM::ModRefInfo::NoModRef,
346 LLVM::ModRefInfo::NoModRef});
347 newFuncOp.setMemoryEffectsAttr(memoryAttr);
355 ConversionPatternRewriter &rewriter,
358 convertedAttrs.reserve(attrsDict.size());
361 return TypeAttr::get(
362 converter.convertType(cast<TypeAttr>(attr.getValue()).getValue()));
364 if (attr.getName().getValue() == LLVM::LLVMDialect::getByValAttrName()) {
365 convertedAttrs.push_back(rewriter.getNamedAttr(
366 LLVM::LLVMDialect::getByValAttrName(), convert(attr)));
367 }
else if (attr.getName().getValue() ==
368 LLVM::LLVMDialect::getByRefAttrName()) {
369 convertedAttrs.push_back(rewriter.getNamedAttr(
370 LLVM::LLVMDialect::getByRefAttrName(), convert(attr)));
371 }
else if (attr.getName().getValue() ==
372 LLVM::LLVMDialect::getStructRetAttrName()) {
373 convertedAttrs.push_back(rewriter.getNamedAttr(
374 LLVM::LLVMDialect::getStructRetAttrName(), convert(attr)));
375 }
else if (attr.getName().getValue() ==
376 LLVM::LLVMDialect::getInAllocaAttrName()) {
377 convertedAttrs.push_back(rewriter.getNamedAttr(
378 LLVM::LLVMDialect::getInAllocaAttrName(), convert(attr)));
380 convertedAttrs.push_back(attr);
383 return convertedAttrs;
387 FunctionOpInterface funcOp, ConversionPatternRewriter &rewriter,
389 LLVM::LLVMFunctionType llvmType, LLVM::LLVMFuncOp newFuncOp) {
392 if (
ArrayAttr resAttrDicts = funcOp.getAllResultAttrs()) {
393 assert(!resAttrDicts.empty() &&
"expected array to be non-empty");
394 if (funcOp.getNumResults() == 1)
395 newFuncOp.setAllResultAttrs(resAttrDicts);
397 if (
ArrayAttr argAttrDicts = funcOp.getAllArgAttrs()) {
399 for (
unsigned i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
403 auto attrsDict = cast<DictionaryAttr>(argAttrDicts[i]);
406 auto mapping = sig.getInputMapping(i);
407 assert(mapping &&
"unexpected deletion of function argument");
411 if (mapping->size == 1) {
412 newArgAttrs[mapping->inputNo] =
413 DictionaryAttr::get(rewriter.getContext(), convertedAttrs);
418 for (
size_t j = 0;
j < mapping->size; ++
j)
419 newArgAttrs[mapping->inputNo +
j] =
420 DictionaryAttr::get(rewriter.getContext(), {});
422 if (!newArgAttrs.empty())
423 newFuncOp.setAllArgAttrs(rewriter.getArrayAttr(newArgAttrs));
428 ConversionPatternRewriter &rewriter,
430 LLVM::LLVMFuncOp newFuncOp) {
431 if (newFuncOp.isExternal())
450 FunctionOpInterface funcOp, ConversionPatternRewriter &rewriter,
453 auto funcTy = dyn_cast<FunctionType>(funcOp.getFunctionType());
455 return rewriter.notifyMatchFailure(
456 funcOp,
"Only support FunctionOpInterface with FunctionType");
464 TypeConverter::SignatureConversion
result(funcOp.getNumArguments());
466 funcOp, converter, useBarePtrCallConv,
result, byValRefNonPtrAttrs);
467 if (failed(llvmType))
468 return rewriter.notifyMatchFailure(funcOp,
"signature conversion failed");
471 bool emitCWrapper = funcOp->hasDiscardableAttrOfType<UnitAttr>(
472 LLVM::LLVMDialect::getEmitCWrapperAttrName());
473 if (!useBarePtrCallConv && emitCWrapper && llvmType->isVarArg())
474 return funcOp.emitError(
"C interface for variadic functions is not "
478 FailureOr<LoweredLLVMFuncAttrs> loweredAttrs =
480 if (failed(loweredAttrs))
481 return rewriter.notifyMatchFailure(funcOp,
482 "failed to lower func attributes");
485 auto newFuncOp =
createLLVMFuncOp(funcOp, rewriter, *llvmType, *loweredAttrs,
493 rewriter.inlineRegionBefore(funcOp.getFunctionBody(), newFuncOp.getBody(),
497 if (!newFuncOp.getBody().empty())
498 rewriter.applySignatureConversion(&newFuncOp.getBody().front(),
result,
509 if (!useBarePtrCallConv && emitCWrapper)
529 matchAndRewrite(func::FuncOp funcOp, OpAdaptor adaptor,
530 ConversionPatternRewriter &rewriter)
const override {
532 cast<FunctionOpInterface>(funcOp.getOperation()), rewriter,
533 *getTypeConverter(), symbolTables);
535 return rewriter.notifyMatchFailure(funcOp,
"Could not convert funcop");
537 rewriter.eraseOp(funcOp);
543 using ConvertOpToLLVMPattern<func::ConstantOp>::ConvertOpToLLVMPattern;
546 matchAndRewrite(func::ConstantOp op, OpAdaptor adaptor,
547 ConversionPatternRewriter &rewriter)
const override {
548 auto type = typeConverter->convertType(op.getResult().getType());
549 if (!type || !LLVM::isCompatibleType(type))
550 return rewriter.notifyMatchFailure(op,
"failed to convert result type");
553 LLVM::AddressOfOp::create(rewriter, op.getLoc(), type, op.getValue());
554 for (
const NamedAttribute &attr :
555 op->getDiscardableAttrDictionary().getValue()) {
556 if (attr.getName().strref() ==
"value")
558 newOp->setDiscardableAttr(attr.getName(), attr.getValue());
560 rewriter.replaceOp(op, newOp->getResults());
567template <
typename CallOpType>
569 using ConvertOpToLLVMPattern<CallOpType>::ConvertOpToLLVMPattern;
570 using Super = CallOpInterfaceLowering<CallOpType>;
571 using Base = ConvertOpToLLVMPattern<CallOpType>;
574 LogicalResult matchAndRewriteImpl(CallOpType callOp, Adaptor adaptor,
575 ConversionPatternRewriter &rewriter,
576 bool useBarePtrCallConv =
false)
const {
578 Type packedResult =
nullptr;
579 SmallVector<SmallVector<Type>> groupedResultTypes;
580 unsigned numResults = callOp.getNumResults();
581 auto resultTypes = llvm::to_vector<4>(callOp.getResultTypes());
582 int64_t numConvertedTypes = 0;
583 if (numResults != 0) {
584 if (!(packedResult = this->getTypeConverter()->packFunctionResults(
585 resultTypes, useBarePtrCallConv, &groupedResultTypes,
586 &numConvertedTypes)))
590 if (useBarePtrCallConv) {
591 for (
auto it : callOp->getOperands()) {
592 Type operandType = it.getType();
593 if (isa<UnrankedMemRefType>(operandType)) {
600 auto promoted = this->getTypeConverter()->promoteOperands(
601 callOp.getLoc(), callOp->getOperands(),
602 adaptor.getOperands(), rewriter, useBarePtrCallConv);
603 LLVM::CallOp::Properties properties{};
604 LLVM::CallOp::populateDefaultProperties(
605 OperationName(LLVM::CallOp::getOperationName(), rewriter.getContext()),
607 properties.operandSegmentSizes = {
static_cast<int32_t
>(promoted.size()), 0};
608 properties.op_bundle_sizes = rewriter.getDenseI32ArrayAttr({});
609 auto newOp = LLVM::CallOp::create(
610 rewriter, callOp.getLoc(),
612 properties, callOp->getDiscardableAttrDictionary().getValue());
613 if constexpr (std::is_same_v<CallOpType, func::CallOp>)
614 newOp.setCalleeAttr(callOp.getCalleeAttr());
623 auto getUnpackedResult = [&](
unsigned i) -> Value {
624 assert(numConvertedTypes > 0 &&
"convert op has no results");
625 if (numConvertedTypes == 1) {
626 assert(i == 0 &&
"out of bounds: converted op has only one result");
627 return newOp->getResult(0);
631 return LLVM::ExtractValueOp::create(rewriter, callOp.getLoc(),
632 newOp->getResult(0), i);
638 SmallVector<SmallVector<Value>> results;
639 results.reserve(numResults);
640 unsigned counter = 0;
641 for (
unsigned i = 0; i < numResults; ++i) {
642 SmallVector<Value> &group = results.emplace_back();
643 for (
unsigned j = 0, e = groupedResultTypes[i].size(); j < e; ++j)
644 group.push_back(getUnpackedResult(counter++));
648 for (
unsigned i = 0; i < numResults; ++i) {
649 Type origType = resultTypes[i];
650 auto memrefType = dyn_cast<MemRefType>(origType);
651 auto unrankedMemrefType = dyn_cast<UnrankedMemRefType>(origType);
652 if (useBarePtrCallConv && memrefType) {
655 assert(results[i].size() == 1 &&
"expected one converted result");
656 results[i].front() = MemRefDescriptor::fromStaticShape(
657 rewriter, callOp.getLoc(), *this->getTypeConverter(), memrefType,
660 if (unrankedMemrefType) {
661 assert(!useBarePtrCallConv &&
"unranked memref is not supported in the "
662 "bare-ptr calling convention");
663 assert(results[i].size() == 1 &&
"expected one converted result");
664 Value desc = this->copyUnrankedDescriptor(
665 rewriter, callOp.getLoc(), unrankedMemrefType, results[i].front(),
669 results[i].front() = desc;
673 rewriter.replaceOpWithMultiple(callOp, results);
678class CallOpLowering :
public CallOpInterfaceLowering<func::CallOp> {
680 explicit CallOpLowering(
const LLVMTypeConverter &typeConverter,
681 SymbolTableCollection *symbolTables =
nullptr,
682 PatternBenefit benefit = 1)
683 : CallOpInterfaceLowering<func::CallOp>(typeConverter, benefit),
684 symbolTables(symbolTables) {}
687 matchAndRewrite(func::CallOp callOp, OneToNOpAdaptor adaptor,
688 ConversionPatternRewriter &rewriter)
const override {
689 bool useBarePtrCallConv =
false;
690 if (getTypeConverter()->getOptions().useBarePtrCallConv) {
691 useBarePtrCallConv =
true;
692 }
else if (symbolTables !=
nullptr) {
695 symbolTables->lookupNearestSymbolFrom(callOp, callOp.getCalleeAttr());
705 return matchAndRewriteImpl(callOp, adaptor, rewriter, useBarePtrCallConv);
709 SymbolTableCollection *symbolTables =
nullptr;
712struct CallIndirectOpLowering
713 :
public CallOpInterfaceLowering<func::CallIndirectOp> {
717 matchAndRewrite(func::CallIndirectOp callIndirectOp, OneToNOpAdaptor adaptor,
718 ConversionPatternRewriter &rewriter)
const override {
719 return matchAndRewriteImpl(callIndirectOp, adaptor, rewriter);
723struct UnrealizedConversionCastOpLowering
725 using ConvertOpToLLVMPattern<
726 UnrealizedConversionCastOp>::ConvertOpToLLVMPattern;
729 matchAndRewrite(UnrealizedConversionCastOp op, OpAdaptor adaptor,
730 ConversionPatternRewriter &rewriter)
const override {
731 SmallVector<Type> convertedTypes;
732 if (succeeded(typeConverter->convertTypes(op.getOutputs().getTypes(),
734 convertedTypes == adaptor.getInputs().getTypes()) {
735 rewriter.replaceOp(op, adaptor.getInputs());
739 convertedTypes.clear();
740 if (succeeded(typeConverter->convertTypes(adaptor.getInputs().getTypes(),
742 convertedTypes == op.getOutputs().getType()) {
743 rewriter.replaceOp(op, adaptor.getInputs());
757 using ConvertOpToLLVMPattern<func::ReturnOp>::ConvertOpToLLVMPattern;
760 matchAndRewrite(func::ReturnOp op, OneToNOpAdaptor adaptor,
761 ConversionPatternRewriter &rewriter)
const override {
762 Location loc = op.getLoc();
763 SmallVector<Value, 4> updatedOperands;
765 auto funcOp = op->getParentOfType<LLVM::LLVMFuncOp>();
766 bool useBarePtrCallConv =
769 for (
auto [oldOperand, newOperands] :
770 llvm::zip_equal(op->getOperands(), adaptor.getOperands())) {
771 Type oldTy = oldOperand.getType();
772 if (
auto memRefType = dyn_cast<MemRefType>(oldTy)) {
773 assert(newOperands.size() == 1 &&
"expected one converted result");
774 if (useBarePtrCallConv &&
775 getTypeConverter()->canConvertToBarePtr(memRefType)) {
778 MemRefDescriptor memrefDesc(newOperands.front());
779 updatedOperands.push_back(memrefDesc.allocatedPtr(rewriter, loc));
782 }
else if (
auto unrankedMemRefType =
783 dyn_cast<UnrankedMemRefType>(oldTy)) {
784 assert(newOperands.size() == 1 &&
"expected one converted result");
785 if (useBarePtrCallConv) {
791 copyUnrankedDescriptor(rewriter, loc, unrankedMemRefType,
792 newOperands.front(),
true);
795 updatedOperands.push_back(updatedDesc);
799 llvm::append_range(updatedOperands, newOperands);
803 if (updatedOperands.size() <= 1) {
804 rewriter.replaceOpWithNewOp<LLVM::ReturnOp>(
806 op->getDiscardableAttrDictionary().getValue());
812 auto packedType = getTypeConverter()->packFunctionResults(
813 op.getOperandTypes(), useBarePtrCallConv);
815 return rewriter.notifyMatchFailure(op,
"could not convert result types");
818 Value packed = LLVM::PoisonOp::create(rewriter, loc, packedType);
819 for (
auto [idx, operand] : llvm::enumerate(updatedOperands)) {
820 packed = LLVM::InsertValueOp::create(rewriter, loc, packed, operand, idx);
822 rewriter.replaceOpWithNewOp<LLVM::ReturnOp>(
823 op,
TypeRange(), packed, op->getDiscardableAttrDictionary().getValue());
832 patterns.
add<FuncOpConversion>(converter, symbolTables);
839 patterns.
add<CallIndirectOpLowering>(converter);
840 patterns.
add<CallOpLowering>(converter, symbolTables);
841 patterns.
add<ConstantOpLowering>(converter);
842 patterns.
add<ReturnOpLowering>(converter);
847struct ConvertFuncToLLVMPass
848 :
public impl::ConvertFuncToLLVMPassBase<ConvertFuncToLLVMPass> {
852 void runOnOperation()
override {
853 ModuleOp m = getOperation();
854 StringRef dataLayout;
855 auto dataLayoutAttr = dyn_cast_or_null<StringAttr>(
856 m->getDiscardableAttr(LLVM::LLVMDialect::getDataLayoutAttrName()));
858 dataLayout = dataLayoutAttr.getValue();
860 if (failed(LLVM::LLVMDialect::verifyDataLayoutString(
861 dataLayout, [
this](
const Twine &message) {
862 getOperation().emitError() << message.str();
868 const auto &dataLayoutAnalysis = getAnalysis<DataLayoutAnalysis>();
871 dataLayoutAnalysis.getAtOrAbove(m));
872 options.useBarePtrCallConv = useBarePtrCallConv;
874 options.overrideIndexBitwidth(indexBitwidth);
875 options.dataLayout = llvm::DataLayout(dataLayout);
878 &dataLayoutAnalysis);
881 SymbolTableCollection symbolTables;
887 if (
failed(applyPartialConversion(m,
target, std::move(patterns))))
892struct SetLLVMModuleDataLayoutPass
893 :
public impl::SetLLVMModuleDataLayoutPassBase<
894 SetLLVMModuleDataLayoutPass> {
898 void runOnOperation()
override {
899 if (
failed(LLVM::LLVMDialect::verifyDataLayoutString(
900 this->dataLayout, [
this](
const Twine &message) {
901 getOperation().emitError() << message.str();
906 ModuleOp m = getOperation();
907 m->setDiscardableAttr(LLVM::LLVMDialect::getDataLayoutAttrName(),
908 StringAttr::get(m.getContext(), this->dataLayout));
919struct FuncToLLVMDialectInterface :
public ConvertToLLVMPatternInterface {
920 FuncToLLVMDialectInterface(Dialect *dialect)
921 : ConvertToLLVMPatternInterface(dialect) {}
924 void populateConvertToLLVMConversionPatterns(
925 ConversionTarget &
target, LLVMTypeConverter &typeConverter,
926 RewritePatternSet &patterns)
const final {
934 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 LLVM::LLVMFuncOp createLLVMFuncOp(FunctionOpInterface funcOp, ConversionPatternRewriter &rewriter, LLVM::LLVMFunctionType llvmType, LoweredLLVMFuncAttrs &loweredAttrs, SymbolTableCollection *symbolTables)
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 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 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)
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...
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.
Operation * getParentWithTrait()
Returns the closest surrounding parent operation with trait Trait.
bool hasDiscardableAttr(StringRef name)
Return true if this operation has a discardable attribute with the provided name.
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)
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< LoweredLLVMFuncAttrs > lowerDiscardableAttrsForLLVMFunc(FunctionOpInterface funcOp, Type llvmFuncType)
Partition funcOp's discardables for llvm.func: sym_name, function_type, and typed properties from llv...
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.
Result of lowering discardable attributes from a FunctionOpInterface to what llvm....
LLVM::LLVMFuncOp::Properties properties
NamedAttrList discardableAttrs
Eliminates variable at the specified position using Fourier-Motzkin variable elimination.