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();
83 FunctionOpInterface funcOp,
84 LLVM::LLVMFuncOp wrapperFuncOp) {
85 auto argAttrs = funcOp.getAllArgAttrs();
86 if (!resultStructType) {
87 if (
auto resAttrs = funcOp.getAllResultAttrs())
88 wrapperFuncOp.setAllResultAttrs(resAttrs);
90 wrapperFuncOp.setAllArgAttrs(argAttrs);
97 argAttributes.append(argAttrs.begin(), argAttrs.end());
98 wrapperFuncOp.setAllArgAttrs(argAttributes);
101 cast<FunctionOpInterface>(wrapperFuncOp.getOperation())
102 .setVisibility(funcOp.getVisibility());
115 FunctionOpInterface funcOp,
116 LLVM::LLVMFuncOp newFuncOp) {
117 auto type = cast<FunctionType>(funcOp.getFunctionType());
118 auto [wrapperFuncType, resultStructType] =
124 auto wrapperFuncOp = LLVM::LLVMFuncOp::create(
125 rewriter, loc, llvm::formatv(
"_mlir_ciface_{0}", funcOp.getName()).str(),
126 wrapperFuncType, LLVM::Linkage::External,
false,
127 LLVM::CConv::C,
nullptr, attributes);
134 size_t argOffset = resultStructType ? 1 : 0;
135 for (
auto [
index, argType] : llvm::enumerate(type.getInputs())) {
136 Value arg = wrapperFuncOp.getArgument(
index + argOffset);
137 if (
auto memrefType = dyn_cast<MemRefType>(argType)) {
138 Value loaded = LLVM::LoadOp::create(
139 rewriter, loc, typeConverter.convertType(memrefType), arg);
143 if (isa<UnrankedMemRefType>(argType)) {
144 Value loaded = LLVM::LoadOp::create(
145 rewriter, loc, typeConverter.convertType(argType), arg);
153 auto call = LLVM::CallOp::create(rewriter, loc, newFuncOp, args);
155 if (resultStructType) {
156 LLVM::StoreOp::create(rewriter, loc, call.getResult(),
157 wrapperFuncOp.getArgument(0));
158 LLVM::ReturnOp::create(rewriter, loc,
ValueRange{});
160 LLVM::ReturnOp::create(rewriter, loc, call.getResults());
175 FunctionOpInterface funcOp,
176 LLVM::LLVMFuncOp newFuncOp) {
179 auto [wrapperType, resultStructType] =
181 cast<FunctionType>(funcOp.getFunctionType()));
185 assert(wrapperType &&
"unexpected type conversion failure");
191 auto wrapperFunc = LLVM::LLVMFuncOp::create(
192 builder, loc, llvm::formatv(
"_mlir_ciface_{0}", funcOp.getName()).str(),
193 wrapperType, LLVM::Linkage::External,
false,
194 LLVM::CConv::C,
nullptr, attributes);
198 newFuncOp.setLinkage(LLVM::Linkage::Private);
202 FunctionType type = cast<FunctionType>(funcOp.getFunctionType());
204 args.reserve(type.getNumInputs());
205 ValueRange wrapperArgsRange(newFuncOp.getArguments());
207 if (resultStructType) {
209 Type resultType = cast<LLVM::LLVMFunctionType>(wrapperType).getParamType(0);
210 Value one = LLVM::ConstantOp::create(
211 builder, loc, typeConverter.convertType(builder.
getIndexType()),
214 LLVM::AllocaOp::create(builder, loc, resultType, resultStructType, one);
220 for (
Type input : type.getInputs()) {
223 auto memRefType = dyn_cast<MemRefType>(input);
224 auto unrankedMemRefType = dyn_cast<UnrankedMemRefType>(input);
225 if (memRefType || unrankedMemRefType) {
226 numToDrop = memRefType
232 wrapperArgsRange.take_front(numToDrop))
234 builder, loc, typeConverter, unrankedMemRefType,
235 wrapperArgsRange.take_front(numToDrop));
237 auto ptrTy = LLVM::LLVMPointerType::get(builder.
getContext());
238 Value one = LLVM::ConstantOp::create(
239 builder, loc, typeConverter.convertType(builder.
getIndexType()),
241 Value allocated = LLVM::AllocaOp::create(
242 builder, loc, ptrTy, packed.
getType(), one, 0);
243 LLVM::StoreOp::create(builder, loc, packed, allocated);
246 arg = wrapperArgsRange[0];
250 wrapperArgsRange = wrapperArgsRange.drop_front(numToDrop);
252 assert(wrapperArgsRange.empty() &&
"did not map some of the arguments");
254 auto call = LLVM::CallOp::create(builder, loc, wrapperFunc, args);
256 if (resultStructType) {
258 LLVM::LoadOp::create(builder, loc, resultStructType, args.front());
259 LLVM::ReturnOp::create(builder, loc,
result);
261 LLVM::ReturnOp::create(builder, loc, call.getResults());
270 ArrayRef<std::optional<NamedAttribute>> byValRefNonPtrAttrs,
271 LLVM::LLVMFuncOp funcOp) {
273 if (funcOp.isExternal())
276 ConversionPatternRewriter::InsertionGuard guard(rewriter);
277 rewriter.setInsertionPointToStart(&funcOp.getFunctionBody().front());
279 for (
const auto &[arg, byValRefAttr] :
280 llvm::zip(funcOp.getArguments(), byValRefNonPtrAttrs)) {
286 assert(isa<LLVM::LLVMPointerType>(arg.getType()) &&
287 "Expected LLVM pointer type for argument with "
288 "`llvm.byval`/`llvm.byref` attribute");
289 Type resTy = typeConverter.convertType(
290 cast<TypeAttr>(byValRefAttr->getValue()).getValue());
292 Value valueArg = LLVM::LoadOp::create(rewriter, arg.getLoc(), resTy, arg);
293 rewriter.replaceAllUsesWith(arg, valueArg);
299 bool useBarePtrCallConv, TypeConverter::SignatureConversion &
result,
302 auto llvmType = dyn_cast_or_null<LLVM::LLVMFunctionType>(
304 funcOp, varargsAttr && varargsAttr.getValue(), useBarePtrCallConv,
305 result, byValRefNonPtrAttrs));
312 ConversionPatternRewriter &rewriter,
313 LLVM::LLVMFunctionType llvmType,
317 if (symbolTables && symbolTableOp) {
319 symbolTable.
remove(funcOp);
322 LLVM::CConvAttr::get(rewriter.getContext(), LLVM::CConv::C));
323 auto newFuncOp = LLVM::LLVMFuncOp::create(rewriter, funcOp.getLoc(),
327 if (symbolTables && symbolTableOp) {
328 auto ip = rewriter.getInsertionPoint();
330 symbolTable.
insert(newFuncOp, ip);
333 cast<FunctionOpInterface>(newFuncOp.getOperation())
334 .setVisibility(funcOp.getVisibility());
337 if (funcOp->hasAttr(LLVM::LLVMDialect::getReadnoneAttrName())) {
338 auto memoryAttr = LLVM::MemoryEffectsAttr::get(
339 rewriter.getContext(), {LLVM::ModRefInfo::NoModRef,
340 LLVM::ModRefInfo::NoModRef,
341 LLVM::ModRefInfo::NoModRef,
342 LLVM::ModRefInfo::NoModRef,
343 LLVM::ModRefInfo::NoModRef,
344 LLVM::ModRefInfo::NoModRef});
345 newFuncOp.setMemoryEffectsAttr(memoryAttr);
353 ConversionPatternRewriter &rewriter,
356 convertedAttrs.reserve(attrsDict.size());
359 return TypeAttr::get(
360 converter.convertType(cast<TypeAttr>(attr.getValue()).getValue()));
362 if (attr.getName().getValue() == LLVM::LLVMDialect::getByValAttrName()) {
363 convertedAttrs.push_back(rewriter.getNamedAttr(
364 LLVM::LLVMDialect::getByValAttrName(), convert(attr)));
365 }
else if (attr.getName().getValue() ==
366 LLVM::LLVMDialect::getByRefAttrName()) {
367 convertedAttrs.push_back(rewriter.getNamedAttr(
368 LLVM::LLVMDialect::getByRefAttrName(), convert(attr)));
369 }
else if (attr.getName().getValue() ==
370 LLVM::LLVMDialect::getStructRetAttrName()) {
371 convertedAttrs.push_back(rewriter.getNamedAttr(
372 LLVM::LLVMDialect::getStructRetAttrName(), convert(attr)));
373 }
else if (attr.getName().getValue() ==
374 LLVM::LLVMDialect::getInAllocaAttrName()) {
375 convertedAttrs.push_back(rewriter.getNamedAttr(
376 LLVM::LLVMDialect::getInAllocaAttrName(), convert(attr)));
378 convertedAttrs.push_back(attr);
381 return convertedAttrs;
385 FunctionOpInterface funcOp, ConversionPatternRewriter &rewriter,
387 LLVM::LLVMFunctionType llvmType, LLVM::LLVMFuncOp newFuncOp) {
390 if (
ArrayAttr resAttrDicts = funcOp.getAllResultAttrs()) {
391 assert(!resAttrDicts.empty() &&
"expected array to be non-empty");
392 if (funcOp.getNumResults() == 1)
393 newFuncOp.setAllResultAttrs(resAttrDicts);
395 if (
ArrayAttr argAttrDicts = funcOp.getAllArgAttrs()) {
397 for (
unsigned i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
401 auto attrsDict = cast<DictionaryAttr>(argAttrDicts[i]);
404 auto mapping = sig.getInputMapping(i);
405 assert(mapping &&
"unexpected deletion of function argument");
409 if (mapping->size == 1) {
410 newArgAttrs[mapping->inputNo] =
411 DictionaryAttr::get(rewriter.getContext(), convertedAttrs);
416 for (
size_t j = 0;
j < mapping->size; ++
j)
417 newArgAttrs[mapping->inputNo +
j] =
418 DictionaryAttr::get(rewriter.getContext(), {});
420 if (!newArgAttrs.empty())
421 newFuncOp.setAllArgAttrs(rewriter.getArrayAttr(newArgAttrs));
426 ConversionPatternRewriter &rewriter,
428 LLVM::LLVMFuncOp newFuncOp) {
429 if (newFuncOp.isExternal())
448 FunctionOpInterface funcOp, ConversionPatternRewriter &rewriter,
451 auto funcTy = dyn_cast<FunctionType>(funcOp.getFunctionType());
453 return rewriter.notifyMatchFailure(
454 funcOp,
"Only support FunctionOpInterface with FunctionType");
462 TypeConverter::SignatureConversion
result(funcOp.getNumArguments());
464 funcOp, converter, useBarePtrCallConv,
result, byValRefNonPtrAttrs);
465 if (failed(llvmType))
466 return rewriter.notifyMatchFailure(funcOp,
"signature conversion failed");
469 bool emitCWrapper = funcOp->hasAttrOfType<UnitAttr>(
470 LLVM::LLVMDialect::getEmitCWrapperAttrName());
471 if (!useBarePtrCallConv && emitCWrapper && llvmType->isVarArg())
472 return funcOp.emitError(
"C interface for variadic functions is not "
476 FailureOr<LoweredLLVMFuncAttrs> loweredAttrs =
478 if (failed(loweredAttrs))
479 return rewriter.notifyMatchFailure(funcOp,
480 "failed to lower func attributes");
483 auto newFuncOp =
createLLVMFuncOp(funcOp, rewriter, *llvmType, *loweredAttrs,
491 rewriter.inlineRegionBefore(funcOp.getFunctionBody(), newFuncOp.getBody(),
495 if (!newFuncOp.getBody().empty())
496 rewriter.applySignatureConversion(&newFuncOp.getBody().front(),
result,
507 if (!useBarePtrCallConv && emitCWrapper)
527 matchAndRewrite(func::FuncOp funcOp, OpAdaptor adaptor,
528 ConversionPatternRewriter &rewriter)
const override {
530 cast<FunctionOpInterface>(funcOp.getOperation()), rewriter,
531 *getTypeConverter(), symbolTables);
533 return rewriter.notifyMatchFailure(funcOp,
"Could not convert funcop");
535 rewriter.eraseOp(funcOp);
541 using ConvertOpToLLVMPattern<func::ConstantOp>::ConvertOpToLLVMPattern;
544 matchAndRewrite(func::ConstantOp op, OpAdaptor adaptor,
545 ConversionPatternRewriter &rewriter)
const override {
546 auto type = typeConverter->convertType(op.getResult().getType());
548 return rewriter.notifyMatchFailure(op,
"failed to convert result type");
551 LLVM::AddressOfOp::create(rewriter, op.getLoc(), type, op.getValue());
552 for (
const NamedAttribute &attr : op->getAttrs()) {
553 if (attr.getName().strref() ==
"value")
555 newOp->setAttr(attr.getName(), attr.getValue());
557 rewriter.replaceOp(op, newOp->getResults());
564template <
typename CallOpType>
566 using ConvertOpToLLVMPattern<CallOpType>::ConvertOpToLLVMPattern;
567 using Super = CallOpInterfaceLowering<CallOpType>;
568 using Base = ConvertOpToLLVMPattern<CallOpType>;
571 LogicalResult matchAndRewriteImpl(CallOpType callOp, Adaptor adaptor,
572 ConversionPatternRewriter &rewriter,
573 bool useBarePtrCallConv =
false)
const {
575 Type packedResult =
nullptr;
576 SmallVector<SmallVector<Type>> groupedResultTypes;
577 unsigned numResults = callOp.getNumResults();
578 auto resultTypes = llvm::to_vector<4>(callOp.getResultTypes());
579 int64_t numConvertedTypes = 0;
580 if (numResults != 0) {
581 if (!(packedResult = this->getTypeConverter()->packFunctionResults(
582 resultTypes, useBarePtrCallConv, &groupedResultTypes,
583 &numConvertedTypes)))
587 if (useBarePtrCallConv) {
588 for (
auto it : callOp->getOperands()) {
589 Type operandType = it.getType();
590 if (isa<UnrankedMemRefType>(operandType)) {
597 auto promoted = this->getTypeConverter()->promoteOperands(
598 callOp.getLoc(), callOp->getOperands(),
599 adaptor.getOperands(), rewriter, useBarePtrCallConv);
600 auto newOp = LLVM::CallOp::create(rewriter, callOp.getLoc(),
603 promoted, callOp->getAttrs());
605 newOp.getProperties().operandSegmentSizes = {
606 static_cast<int32_t
>(promoted.size()), 0};
607 newOp.getProperties().op_bundle_sizes = rewriter.getDenseI32ArrayAttr({});
616 auto getUnpackedResult = [&](
unsigned i) -> Value {
617 assert(numConvertedTypes > 0 &&
"convert op has no results");
618 if (numConvertedTypes == 1) {
619 assert(i == 0 &&
"out of bounds: converted op has only one result");
620 return newOp->getResult(0);
624 return LLVM::ExtractValueOp::create(rewriter, callOp.getLoc(),
625 newOp->getResult(0), i);
631 SmallVector<SmallVector<Value>> results;
632 results.reserve(numResults);
633 unsigned counter = 0;
634 for (
unsigned i = 0; i < numResults; ++i) {
635 SmallVector<Value> &group = results.emplace_back();
636 for (
unsigned j = 0, e = groupedResultTypes[i].size(); j < e; ++j)
637 group.push_back(getUnpackedResult(counter++));
641 for (
unsigned i = 0; i < numResults; ++i) {
642 Type origType = resultTypes[i];
643 auto memrefType = dyn_cast<MemRefType>(origType);
644 auto unrankedMemrefType = dyn_cast<UnrankedMemRefType>(origType);
645 if (useBarePtrCallConv && memrefType) {
648 assert(results[i].size() == 1 &&
"expected one converted result");
649 results[i].front() = MemRefDescriptor::fromStaticShape(
650 rewriter, callOp.getLoc(), *this->getTypeConverter(), memrefType,
653 if (unrankedMemrefType) {
654 assert(!useBarePtrCallConv &&
"unranked memref is not supported in the "
655 "bare-ptr calling convention");
656 assert(results[i].size() == 1 &&
"expected one converted result");
657 Value desc = this->copyUnrankedDescriptor(
658 rewriter, callOp.getLoc(), unrankedMemrefType, results[i].front(),
662 results[i].front() = desc;
666 rewriter.replaceOpWithMultiple(callOp, results);
671class CallOpLowering :
public CallOpInterfaceLowering<func::CallOp> {
673 explicit CallOpLowering(
const LLVMTypeConverter &typeConverter,
674 SymbolTableCollection *symbolTables =
nullptr,
675 PatternBenefit benefit = 1)
676 : CallOpInterfaceLowering<func::CallOp>(typeConverter, benefit),
677 symbolTables(symbolTables) {}
680 matchAndRewrite(func::CallOp callOp, OneToNOpAdaptor adaptor,
681 ConversionPatternRewriter &rewriter)
const override {
682 bool useBarePtrCallConv =
false;
683 if (getTypeConverter()->getOptions().useBarePtrCallConv) {
684 useBarePtrCallConv =
true;
685 }
else if (symbolTables !=
nullptr) {
688 symbolTables->lookupNearestSymbolFrom(callOp, callOp.getCalleeAttr());
698 return matchAndRewriteImpl(callOp, adaptor, rewriter, useBarePtrCallConv);
702 SymbolTableCollection *symbolTables =
nullptr;
705struct CallIndirectOpLowering
706 :
public CallOpInterfaceLowering<func::CallIndirectOp> {
710 matchAndRewrite(func::CallIndirectOp callIndirectOp, OneToNOpAdaptor adaptor,
711 ConversionPatternRewriter &rewriter)
const override {
712 return matchAndRewriteImpl(callIndirectOp, adaptor, rewriter);
716struct UnrealizedConversionCastOpLowering
718 using ConvertOpToLLVMPattern<
719 UnrealizedConversionCastOp>::ConvertOpToLLVMPattern;
722 matchAndRewrite(UnrealizedConversionCastOp op, OpAdaptor adaptor,
723 ConversionPatternRewriter &rewriter)
const override {
724 SmallVector<Type> convertedTypes;
725 if (succeeded(typeConverter->convertTypes(op.getOutputs().getTypes(),
727 convertedTypes == adaptor.getInputs().getTypes()) {
728 rewriter.replaceOp(op, adaptor.getInputs());
732 convertedTypes.clear();
733 if (succeeded(typeConverter->convertTypes(adaptor.getInputs().getTypes(),
735 convertedTypes == op.getOutputs().getType()) {
736 rewriter.replaceOp(op, adaptor.getInputs());
750 using ConvertOpToLLVMPattern<func::ReturnOp>::ConvertOpToLLVMPattern;
753 matchAndRewrite(func::ReturnOp op, OneToNOpAdaptor adaptor,
754 ConversionPatternRewriter &rewriter)
const override {
755 Location loc = op.getLoc();
756 SmallVector<Value, 4> updatedOperands;
758 auto funcOp = op->getParentOfType<LLVM::LLVMFuncOp>();
759 bool useBarePtrCallConv =
762 for (
auto [oldOperand, newOperands] :
763 llvm::zip_equal(op->getOperands(), adaptor.getOperands())) {
764 Type oldTy = oldOperand.getType();
765 if (
auto memRefType = dyn_cast<MemRefType>(oldTy)) {
766 assert(newOperands.size() == 1 &&
"expected one converted result");
767 if (useBarePtrCallConv &&
768 getTypeConverter()->canConvertToBarePtr(memRefType)) {
771 MemRefDescriptor memrefDesc(newOperands.front());
772 updatedOperands.push_back(memrefDesc.allocatedPtr(rewriter, loc));
775 }
else if (
auto unrankedMemRefType =
776 dyn_cast<UnrankedMemRefType>(oldTy)) {
777 assert(newOperands.size() == 1 &&
"expected one converted result");
778 if (useBarePtrCallConv) {
784 copyUnrankedDescriptor(rewriter, loc, unrankedMemRefType,
785 newOperands.front(),
true);
788 updatedOperands.push_back(updatedDesc);
792 llvm::append_range(updatedOperands, newOperands);
796 if (updatedOperands.size() <= 1) {
797 rewriter.replaceOpWithNewOp<LLVM::ReturnOp>(
798 op,
TypeRange(), updatedOperands, op->getAttrs());
804 auto packedType = getTypeConverter()->packFunctionResults(
805 op.getOperandTypes(), useBarePtrCallConv);
807 return rewriter.notifyMatchFailure(op,
"could not convert result types");
810 Value packed = LLVM::PoisonOp::create(rewriter, loc, packedType);
811 for (
auto [idx, operand] : llvm::enumerate(updatedOperands)) {
812 packed = LLVM::InsertValueOp::create(rewriter, loc, packed, operand, idx);
814 rewriter.replaceOpWithNewOp<LLVM::ReturnOp>(op,
TypeRange(), packed,
824 patterns.
add<FuncOpConversion>(converter, symbolTables);
831 patterns.
add<CallIndirectOpLowering>(converter);
832 patterns.
add<CallOpLowering>(converter, symbolTables);
833 patterns.
add<ConstantOpLowering>(converter);
834 patterns.
add<ReturnOpLowering>(converter);
839struct ConvertFuncToLLVMPass
844 void runOnOperation()
override {
845 ModuleOp m = getOperation();
846 StringRef dataLayout;
847 auto dataLayoutAttr = dyn_cast_or_null<StringAttr>(
848 m->getAttr(LLVM::LLVMDialect::getDataLayoutAttrName()));
850 dataLayout = dataLayoutAttr.getValue();
852 if (failed(LLVM::LLVMDialect::verifyDataLayoutString(
853 dataLayout, [
this](
const Twine &message) {
854 getOperation().emitError() << message.str();
860 const auto &dataLayoutAnalysis = getAnalysis<DataLayoutAnalysis>();
863 dataLayoutAnalysis.getAtOrAbove(m));
864 options.useBarePtrCallConv = useBarePtrCallConv;
866 options.overrideIndexBitwidth(indexBitwidth);
867 options.dataLayout = llvm::DataLayout(dataLayout);
870 &dataLayoutAnalysis);
873 SymbolTableCollection symbolTables;
879 if (
failed(applyPartialConversion(m,
target, std::move(patterns))))
884struct SetLLVMModuleDataLayoutPass
886 SetLLVMModuleDataLayoutPass> {
890 void runOnOperation()
override {
891 if (
failed(LLVM::LLVMDialect::verifyDataLayoutString(
892 this->dataLayout, [
this](
const Twine &message) {
893 getOperation().emitError() << message.str();
898 ModuleOp m = getOperation();
899 m->setAttr(LLVM::LLVMDialect::getDataLayoutAttrName(),
900 StringAttr::get(m.getContext(), this->dataLayout));
911struct FuncToLLVMDialectInterface :
public ConvertToLLVMPatternInterface {
912 FuncToLLVMDialectInterface(Dialect *dialect)
913 : ConvertToLLVMPatternInterface(dialect) {}
916 void populateConvertToLLVMConversionPatterns(
917 ConversionTarget &
target, LLVMTypeConverter &typeConverter,
918 RewritePatternSet &patterns)
const final {
926 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.
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.
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.
bool isCompatibleType(Type type)
Returns true if the given type is compatible with the LLVM dialect.
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.