36#include "llvm/ADT/SmallVector.h"
37#include "llvm/IR/Type.h"
38#include "llvm/Support/FormatVariadic.h"
42#define GEN_PASS_DEF_CONVERTFUNCTOLLVMPASS
43#define GEN_PASS_DEF_SETLLVMMODULEDATALAYOUTPASS
44#include "mlir/Conversion/Passes.h.inc"
49#define PASS_NAME "convert-func-to-llvm"
69 attr.getName() == LLVM::LLVMDialect::getReadnoneAttrName())
77 FunctionOpInterface funcOp,
78 LLVM::LLVMFuncOp wrapperFuncOp) {
79 auto argAttrs = funcOp.getAllArgAttrs();
80 if (!resultStructType) {
81 if (
auto resAttrs = funcOp.getAllResultAttrs())
82 wrapperFuncOp.setAllResultAttrs(resAttrs);
84 wrapperFuncOp.setAllArgAttrs(argAttrs);
91 argAttributes.append(argAttrs.begin(), argAttrs.end());
92 wrapperFuncOp.setAllArgAttrs(argAttributes);
95 cast<FunctionOpInterface>(wrapperFuncOp.getOperation())
96 .setVisibility(funcOp.getVisibility());
109 FunctionOpInterface funcOp,
110 LLVM::LLVMFuncOp newFuncOp) {
111 auto type = cast<FunctionType>(funcOp.getFunctionType());
112 auto [wrapperFuncType, resultStructType] =
118 auto wrapperFuncOp = LLVM::LLVMFuncOp::create(
119 rewriter, loc, llvm::formatv(
"_mlir_ciface_{0}", funcOp.getName()).str(),
120 wrapperFuncType, LLVM::Linkage::External,
false,
121 LLVM::CConv::C,
nullptr, attributes);
128 size_t argOffset = resultStructType ? 1 : 0;
129 for (
auto [
index, argType] : llvm::enumerate(type.getInputs())) {
130 Value arg = wrapperFuncOp.getArgument(
index + argOffset);
131 if (
auto memrefType = dyn_cast<MemRefType>(argType)) {
132 Value loaded = LLVM::LoadOp::create(
133 rewriter, loc, typeConverter.convertType(memrefType), arg);
137 if (isa<UnrankedMemRefType>(argType)) {
138 Value loaded = LLVM::LoadOp::create(
139 rewriter, loc, typeConverter.convertType(argType), arg);
147 auto call = LLVM::CallOp::create(rewriter, loc, newFuncOp, args);
149 if (resultStructType) {
150 LLVM::StoreOp::create(rewriter, loc, call.getResult(),
151 wrapperFuncOp.getArgument(0));
152 LLVM::ReturnOp::create(rewriter, loc,
ValueRange{});
154 LLVM::ReturnOp::create(rewriter, loc, call.getResults());
169 FunctionOpInterface funcOp,
170 LLVM::LLVMFuncOp newFuncOp) {
173 auto [wrapperType, resultStructType] =
175 cast<FunctionType>(funcOp.getFunctionType()));
179 assert(wrapperType &&
"unexpected type conversion failure");
185 auto wrapperFunc = LLVM::LLVMFuncOp::create(
186 builder, loc, llvm::formatv(
"_mlir_ciface_{0}", funcOp.getName()).str(),
187 wrapperType, LLVM::Linkage::External,
false,
188 LLVM::CConv::C,
nullptr, attributes);
192 newFuncOp.setLinkage(LLVM::Linkage::Private);
196 FunctionType type = cast<FunctionType>(funcOp.getFunctionType());
198 args.reserve(type.getNumInputs());
199 ValueRange wrapperArgsRange(newFuncOp.getArguments());
201 if (resultStructType) {
203 Type resultType = cast<LLVM::LLVMFunctionType>(wrapperType).getParamType(0);
204 Value one = LLVM::ConstantOp::create(
205 builder, loc, typeConverter.convertType(builder.
getIndexType()),
208 LLVM::AllocaOp::create(builder, loc, resultType, resultStructType, one);
214 for (
Type input : type.getInputs()) {
217 auto memRefType = dyn_cast<MemRefType>(input);
218 auto unrankedMemRefType = dyn_cast<UnrankedMemRefType>(input);
219 if (memRefType || unrankedMemRefType) {
220 numToDrop = memRefType
226 wrapperArgsRange.take_front(numToDrop))
228 builder, loc, typeConverter, unrankedMemRefType,
229 wrapperArgsRange.take_front(numToDrop));
231 auto ptrTy = LLVM::LLVMPointerType::get(builder.
getContext());
232 Value one = LLVM::ConstantOp::create(
233 builder, loc, typeConverter.convertType(builder.
getIndexType()),
235 Value allocated = LLVM::AllocaOp::create(
236 builder, loc, ptrTy, packed.
getType(), one, 0);
237 LLVM::StoreOp::create(builder, loc, packed, allocated);
240 arg = wrapperArgsRange[0];
244 wrapperArgsRange = wrapperArgsRange.drop_front(numToDrop);
246 assert(wrapperArgsRange.empty() &&
"did not map some of the arguments");
248 auto call = LLVM::CallOp::create(builder, loc, wrapperFunc, args);
250 if (resultStructType) {
252 LLVM::LoadOp::create(builder, loc, resultStructType, args.front());
253 LLVM::ReturnOp::create(builder, loc,
result);
255 LLVM::ReturnOp::create(builder, loc, call.getResults());
264 ArrayRef<std::optional<NamedAttribute>> byValRefNonPtrAttrs,
265 LLVM::LLVMFuncOp funcOp) {
267 if (funcOp.isExternal())
270 ConversionPatternRewriter::InsertionGuard guard(rewriter);
271 rewriter.setInsertionPointToStart(&funcOp.getFunctionBody().front());
273 for (
const auto &[arg, byValRefAttr] :
274 llvm::zip(funcOp.getArguments(), byValRefNonPtrAttrs)) {
280 assert(isa<LLVM::LLVMPointerType>(arg.getType()) &&
281 "Expected LLVM pointer type for argument with "
282 "`llvm.byval`/`llvm.byref` attribute");
283 Type resTy = typeConverter.convertType(
284 cast<TypeAttr>(byValRefAttr->getValue()).getValue());
286 Value valueArg = LLVM::LoadOp::create(rewriter, arg.getLoc(), resTy, arg);
287 rewriter.replaceAllUsesWith(arg, valueArg);
292 FunctionOpInterface funcOp, ConversionPatternRewriter &rewriter,
295 auto funcTy = dyn_cast<FunctionType>(funcOp.getFunctionType());
297 return rewriter.notifyMatchFailure(
298 funcOp,
"Only support FunctionOpInterface with FunctionType");
306 TypeConverter::SignatureConversion
result(funcOp.getNumArguments());
307 auto llvmType = dyn_cast_or_null<LLVM::LLVMFunctionType>(
309 funcOp, varargsAttr && varargsAttr.getValue(),
311 byValRefNonPtrAttrs));
313 return rewriter.notifyMatchFailure(funcOp,
"signature conversion failed");
317 if (funcOp->getAttrOfType<UnitAttr>(
318 LLVM::LLVMDialect::getEmitCWrapperAttrName()))
319 if (llvmType.isVarArg())
320 return funcOp.emitError(
"C interface for variadic functions is not "
325 LLVM::Linkage linkage = LLVM::Linkage::External;
331 <<
" attribute not of type LLVM::LinkageAttr";
332 return rewriter.notifyMatchFailure(
333 funcOp,
"Contains linkage attribute not of type LLVM::LinkageAttr");
335 linkage = attr.getLinkage();
339 StringRef readnoneAttrName = LLVM::LLVMDialect::getReadnoneAttrName();
340 if (funcOp->hasAttr(readnoneAttrName)) {
341 auto attr = funcOp->getAttrOfType<UnitAttr>(readnoneAttrName);
343 funcOp->emitError() <<
"Contains " << readnoneAttrName
344 <<
" attribute not of type UnitAttr";
345 return rewriter.notifyMatchFailure(
346 funcOp,
"Contains readnone attribute not of type UnitAttr");
355 if (symbolTables && symbolTableOp) {
357 symbolTable.
remove(funcOp);
360 auto newFuncOp = LLVM::LLVMFuncOp::create(
361 rewriter, funcOp.getLoc(), funcOp.getName(), llvmType, linkage,
362 false, LLVM::CConv::C,
nullptr,
365 if (symbolTables && symbolTableOp) {
366 auto ip = rewriter.getInsertionPoint();
368 symbolTable.
insert(newFuncOp, ip);
371 cast<FunctionOpInterface>(newFuncOp.getOperation())
372 .setVisibility(funcOp.getVisibility());
375 if (funcOp->hasAttr(readnoneAttrName)) {
376 auto memoryAttr = LLVM::MemoryEffectsAttr::get(
377 rewriter.getContext(), {LLVM::ModRefInfo::NoModRef,
378 LLVM::ModRefInfo::NoModRef,
379 LLVM::ModRefInfo::NoModRef,
380 LLVM::ModRefInfo::NoModRef,
381 LLVM::ModRefInfo::NoModRef,
382 LLVM::ModRefInfo::NoModRef});
383 newFuncOp.setMemoryEffectsAttr(memoryAttr);
388 if (
ArrayAttr resAttrDicts = funcOp.getAllResultAttrs()) {
389 assert(!resAttrDicts.empty() &&
"expected array to be non-empty");
390 if (funcOp.getNumResults() == 1)
391 newFuncOp.setAllResultAttrs(resAttrDicts);
393 if (
ArrayAttr argAttrDicts = funcOp.getAllArgAttrs()) {
395 cast<LLVM::LLVMFunctionType>(llvmType).getNumParams());
396 for (
unsigned i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
401 auto attrsDict = cast<DictionaryAttr>(argAttrDicts[i]);
402 convertedAttrs.reserve(attrsDict.size());
405 return TypeAttr::get(converter.convertType(
406 cast<TypeAttr>(attr.getValue()).getValue()));
408 if (attr.getName().getValue() ==
409 LLVM::LLVMDialect::getByValAttrName()) {
410 convertedAttrs.push_back(rewriter.getNamedAttr(
411 LLVM::LLVMDialect::getByValAttrName(), convert(attr)));
412 }
else if (attr.getName().getValue() ==
413 LLVM::LLVMDialect::getByRefAttrName()) {
414 convertedAttrs.push_back(rewriter.getNamedAttr(
415 LLVM::LLVMDialect::getByRefAttrName(), convert(attr)));
416 }
else if (attr.getName().getValue() ==
417 LLVM::LLVMDialect::getStructRetAttrName()) {
418 convertedAttrs.push_back(rewriter.getNamedAttr(
419 LLVM::LLVMDialect::getStructRetAttrName(), convert(attr)));
420 }
else if (attr.getName().getValue() ==
421 LLVM::LLVMDialect::getInAllocaAttrName()) {
422 convertedAttrs.push_back(rewriter.getNamedAttr(
423 LLVM::LLVMDialect::getInAllocaAttrName(), convert(attr)));
425 convertedAttrs.push_back(attr);
428 auto mapping =
result.getInputMapping(i);
429 assert(mapping &&
"unexpected deletion of function argument");
433 if (mapping->size == 1) {
434 newArgAttrs[mapping->inputNo] =
435 DictionaryAttr::get(rewriter.getContext(), convertedAttrs);
440 for (
size_t j = 0;
j < mapping->size; ++
j)
441 newArgAttrs[mapping->inputNo +
j] =
442 DictionaryAttr::get(rewriter.getContext(), {});
444 if (!newArgAttrs.empty())
445 newFuncOp.setAllArgAttrs(rewriter.getArrayAttr(newArgAttrs));
448 rewriter.inlineRegionBefore(funcOp.getFunctionBody(), newFuncOp.getBody(),
452 if (!newFuncOp.getBody().empty())
453 rewriter.applySignatureConversion(&newFuncOp.getBody().front(),
result,
463 if (funcOp->getAttrOfType<UnitAttr>(
464 LLVM::LLVMDialect::getEmitCWrapperAttrName())) {
465 if (newFuncOp.isExternal())
491 matchAndRewrite(func::FuncOp funcOp, OpAdaptor adaptor,
492 ConversionPatternRewriter &rewriter)
const override {
494 cast<FunctionOpInterface>(funcOp.getOperation()), rewriter,
495 *getTypeConverter(), symbolTables);
497 return rewriter.notifyMatchFailure(funcOp,
"Could not convert funcop");
499 rewriter.eraseOp(funcOp);
505 using ConvertOpToLLVMPattern<func::ConstantOp>::ConvertOpToLLVMPattern;
508 matchAndRewrite(func::ConstantOp op, OpAdaptor adaptor,
509 ConversionPatternRewriter &rewriter)
const override {
510 auto type = typeConverter->convertType(op.getResult().getType());
512 return rewriter.notifyMatchFailure(op,
"failed to convert result type");
515 LLVM::AddressOfOp::create(rewriter, op.getLoc(), type, op.getValue());
516 for (
const NamedAttribute &attr : op->getAttrs()) {
517 if (attr.getName().strref() ==
"value")
519 newOp->setAttr(attr.getName(), attr.getValue());
521 rewriter.replaceOp(op, newOp->getResults());
528template <
typename CallOpType>
530 using ConvertOpToLLVMPattern<CallOpType>::ConvertOpToLLVMPattern;
531 using Super = CallOpInterfaceLowering<CallOpType>;
532 using Base = ConvertOpToLLVMPattern<CallOpType>;
535 LogicalResult matchAndRewriteImpl(CallOpType callOp, Adaptor adaptor,
536 ConversionPatternRewriter &rewriter,
537 bool useBarePtrCallConv =
false)
const {
539 Type packedResult =
nullptr;
540 SmallVector<SmallVector<Type>> groupedResultTypes;
541 unsigned numResults = callOp.getNumResults();
542 auto resultTypes = llvm::to_vector<4>(callOp.getResultTypes());
543 int64_t numConvertedTypes = 0;
544 if (numResults != 0) {
545 if (!(packedResult = this->getTypeConverter()->packFunctionResults(
546 resultTypes, useBarePtrCallConv, &groupedResultTypes,
547 &numConvertedTypes)))
551 if (useBarePtrCallConv) {
552 for (
auto it : callOp->getOperands()) {
553 Type operandType = it.getType();
554 if (isa<UnrankedMemRefType>(operandType)) {
561 auto promoted = this->getTypeConverter()->promoteOperands(
562 callOp.getLoc(), callOp->getOperands(),
563 adaptor.getOperands(), rewriter, useBarePtrCallConv);
564 auto newOp = LLVM::CallOp::create(rewriter, callOp.getLoc(),
567 promoted, callOp->getAttrs());
569 newOp.getProperties().operandSegmentSizes = {
570 static_cast<int32_t
>(promoted.size()), 0};
571 newOp.getProperties().op_bundle_sizes = rewriter.getDenseI32ArrayAttr({});
580 auto getUnpackedResult = [&](
unsigned i) -> Value {
581 assert(numConvertedTypes > 0 &&
"convert op has no results");
582 if (numConvertedTypes == 1) {
583 assert(i == 0 &&
"out of bounds: converted op has only one result");
584 return newOp->getResult(0);
588 return LLVM::ExtractValueOp::create(rewriter, callOp.getLoc(),
589 newOp->getResult(0), i);
595 SmallVector<SmallVector<Value>> results;
596 results.reserve(numResults);
597 unsigned counter = 0;
598 for (
unsigned i = 0; i < numResults; ++i) {
599 SmallVector<Value> &group = results.emplace_back();
600 for (
unsigned j = 0, e = groupedResultTypes[i].size(); j < e; ++j)
601 group.push_back(getUnpackedResult(counter++));
605 for (
unsigned i = 0; i < numResults; ++i) {
606 Type origType = resultTypes[i];
607 auto memrefType = dyn_cast<MemRefType>(origType);
608 auto unrankedMemrefType = dyn_cast<UnrankedMemRefType>(origType);
609 if (useBarePtrCallConv && memrefType) {
612 assert(results[i].size() == 1 &&
"expected one converted result");
613 results[i].front() = MemRefDescriptor::fromStaticShape(
614 rewriter, callOp.getLoc(), *this->getTypeConverter(), memrefType,
617 if (unrankedMemrefType) {
618 assert(!useBarePtrCallConv &&
"unranked memref is not supported in the "
619 "bare-ptr calling convention");
620 assert(results[i].size() == 1 &&
"expected one converted result");
621 Value desc = this->copyUnrankedDescriptor(
622 rewriter, callOp.getLoc(), unrankedMemrefType, results[i].front(),
626 results[i].front() = desc;
630 rewriter.replaceOpWithMultiple(callOp, results);
635class CallOpLowering :
public CallOpInterfaceLowering<func::CallOp> {
637 explicit CallOpLowering(
const LLVMTypeConverter &typeConverter,
638 SymbolTableCollection *symbolTables =
nullptr,
639 PatternBenefit benefit = 1)
640 : CallOpInterfaceLowering<func::CallOp>(typeConverter, benefit),
641 symbolTables(symbolTables) {}
644 matchAndRewrite(func::CallOp callOp, OneToNOpAdaptor adaptor,
645 ConversionPatternRewriter &rewriter)
const override {
646 bool useBarePtrCallConv =
false;
647 if (getTypeConverter()->getOptions().useBarePtrCallConv) {
648 useBarePtrCallConv =
true;
649 }
else if (symbolTables !=
nullptr) {
652 symbolTables->lookupNearestSymbolFrom(callOp, callOp.getCalleeAttr());
662 return matchAndRewriteImpl(callOp, adaptor, rewriter, useBarePtrCallConv);
666 SymbolTableCollection *symbolTables =
nullptr;
669struct CallIndirectOpLowering
670 :
public CallOpInterfaceLowering<func::CallIndirectOp> {
674 matchAndRewrite(func::CallIndirectOp callIndirectOp, OneToNOpAdaptor adaptor,
675 ConversionPatternRewriter &rewriter)
const override {
676 return matchAndRewriteImpl(callIndirectOp, adaptor, rewriter);
680struct UnrealizedConversionCastOpLowering
682 using ConvertOpToLLVMPattern<
683 UnrealizedConversionCastOp>::ConvertOpToLLVMPattern;
686 matchAndRewrite(UnrealizedConversionCastOp op, OpAdaptor adaptor,
687 ConversionPatternRewriter &rewriter)
const override {
688 SmallVector<Type> convertedTypes;
689 if (succeeded(typeConverter->convertTypes(op.getOutputs().getTypes(),
691 convertedTypes == adaptor.getInputs().getTypes()) {
692 rewriter.replaceOp(op, adaptor.getInputs());
696 convertedTypes.clear();
697 if (succeeded(typeConverter->convertTypes(adaptor.getInputs().getTypes(),
699 convertedTypes == op.getOutputs().getType()) {
700 rewriter.replaceOp(op, adaptor.getInputs());
714 using ConvertOpToLLVMPattern<func::ReturnOp>::ConvertOpToLLVMPattern;
717 matchAndRewrite(func::ReturnOp op, OneToNOpAdaptor adaptor,
718 ConversionPatternRewriter &rewriter)
const override {
719 Location loc = op.getLoc();
720 SmallVector<Value, 4> updatedOperands;
722 auto funcOp = op->getParentOfType<LLVM::LLVMFuncOp>();
723 bool useBarePtrCallConv =
726 for (
auto [oldOperand, newOperands] :
727 llvm::zip_equal(op->getOperands(), adaptor.getOperands())) {
728 Type oldTy = oldOperand.getType();
729 if (
auto memRefType = dyn_cast<MemRefType>(oldTy)) {
730 assert(newOperands.size() == 1 &&
"expected one converted result");
731 if (useBarePtrCallConv &&
732 getTypeConverter()->canConvertToBarePtr(memRefType)) {
735 MemRefDescriptor memrefDesc(newOperands.front());
736 updatedOperands.push_back(memrefDesc.allocatedPtr(rewriter, loc));
739 }
else if (
auto unrankedMemRefType =
740 dyn_cast<UnrankedMemRefType>(oldTy)) {
741 assert(newOperands.size() == 1 &&
"expected one converted result");
742 if (useBarePtrCallConv) {
748 copyUnrankedDescriptor(rewriter, loc, unrankedMemRefType,
749 newOperands.front(),
true);
752 updatedOperands.push_back(updatedDesc);
756 llvm::append_range(updatedOperands, newOperands);
760 if (updatedOperands.size() <= 1) {
761 rewriter.replaceOpWithNewOp<LLVM::ReturnOp>(
762 op,
TypeRange(), updatedOperands, op->getAttrs());
768 auto packedType = getTypeConverter()->packFunctionResults(
769 op.getOperandTypes(), useBarePtrCallConv);
771 return rewriter.notifyMatchFailure(op,
"could not convert result types");
774 Value packed = LLVM::PoisonOp::create(rewriter, loc, packedType);
775 for (
auto [idx, operand] : llvm::enumerate(updatedOperands)) {
776 packed = LLVM::InsertValueOp::create(rewriter, loc, packed, operand, idx);
778 rewriter.replaceOpWithNewOp<LLVM::ReturnOp>(op,
TypeRange(), packed,
788 patterns.add<FuncOpConversion>(converter, symbolTables);
795 patterns.add<CallIndirectOpLowering>(converter);
796 patterns.add<CallOpLowering>(converter, symbolTables);
797 patterns.add<ConstantOpLowering>(converter);
798 patterns.add<ReturnOpLowering>(converter);
803struct ConvertFuncToLLVMPass
808 void runOnOperation()
override {
809 ModuleOp m = getOperation();
810 StringRef dataLayout;
811 auto dataLayoutAttr = dyn_cast_or_null<StringAttr>(
812 m->getAttr(LLVM::LLVMDialect::getDataLayoutAttrName()));
814 dataLayout = dataLayoutAttr.getValue();
816 if (failed(LLVM::LLVMDialect::verifyDataLayoutString(
817 dataLayout, [
this](
const Twine &message) {
818 getOperation().emitError() << message.str();
824 const auto &dataLayoutAnalysis = getAnalysis<DataLayoutAnalysis>();
827 dataLayoutAnalysis.getAtOrAbove(m));
828 options.useBarePtrCallConv = useBarePtrCallConv;
830 options.overrideIndexBitwidth(indexBitwidth);
831 options.dataLayout = llvm::DataLayout(dataLayout);
834 &dataLayoutAnalysis);
837 SymbolTableCollection symbolTables;
848struct SetLLVMModuleDataLayoutPass
850 SetLLVMModuleDataLayoutPass> {
854 void runOnOperation()
override {
855 if (
failed(LLVM::LLVMDialect::verifyDataLayoutString(
856 this->dataLayout, [
this](
const Twine &message) {
857 getOperation().emitError() << message.str();
862 ModuleOp m = getOperation();
863 m->setAttr(LLVM::LLVMDialect::getDataLayoutAttrName(),
864 StringAttr::get(m.getContext(), this->dataLayout));
879 void populateConvertToLLVMConversionPatterns(
880 ConversionTarget &
target, LLVMTypeConverter &typeConverter,
881 RewritePatternSet &
patterns)
const final {
889 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 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 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)
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
Base class for dialect interfaces providing translation to LLVM IR.
ConvertToLLVMPatternInterface(Dialect *dialect)
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.
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.
const FrozenRewritePatternSet & patterns
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.
Eliminates variable at the specified position using Fourier-Motzkin variable elimination.