17#include "mlir/Conversion/LLVMCommon/ConversionTarget.h"
18#include "mlir/Conversion/LLVMCommon/Pattern.h"
19#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
20#include "mlir/IR/Iterators.h"
21#include "mlir/Pass/Pass.h"
22#include "mlir/Transforms/DialectConversion.h"
23#include "llvm/ADT/TypeSwitch.h"
26#define GEN_PASS_DEF_CONVERTHWTOLLVM
27#include "circt/Conversion/Passes.h.inc"
41 return TypeSwitch<Type, uint32_t>(type)
43 [&](hw::ArrayType ty) {
return ty.getNumElements() - index - 1; })
44 .Case<hw::StructType>([&](hw::StructType ty) {
45 return ty.getElements().size() - index - 1;
51 StringRef fieldName) {
52 auto fieldIter = type.getElements();
55 for (
const auto *iter = fieldIter.begin(); iter != fieldIter.end(); ++iter) {
56 if (iter->name == fieldName) {
64 llvm_unreachable(
"Field name attribute of hw::StructExtractOp invalid");
75static Value
zextByOne(Location loc, ConversionPatternRewriter &rewriter,
77 auto valueTy = value.getType();
78 auto zextTy = IntegerType::get(valueTy.getContext(),
79 valueTy.getIntOrFloatBitWidth() + 1);
80 return LLVM::ZExtOp::create(rewriter, loc, zextTy, value);
89 auto oneC = LLVM::ConstantOp::create(
90 builder, loc, IntegerType::get(builder.getContext(), 32),
91 builder.getI32IntegerAttr(1));
92 Value ptr = LLVM::AllocaOp::create(
93 builder, loc, LLVM::LLVMPointerType::get(builder.getContext()),
94 spillVal.getType(), oneC,
96 LLVM::StoreOp::create(builder, loc, spillVal, ptr);
101 LLVMTypeConverter &converter,
102 Operation *containerOp) {
103 OpBuilder::InsertionGuard g(builder);
104 containerOp->walk<mlir::WalkOrder::PostOrder, mlir::ReverseIterator>(
106 if (isa_and_nonnull<hw::HWDialect>(op->getDialect()))
108 auto hasSpillingUser = [](Value arrVal) ->
bool {
109 for (
auto user : arrVal.getUsers())
110 if (isa<hw::ArrayGetOp, hw::ArraySliceOp>(user))
115 for (
auto ®ion : op->getRegions()) {
116 for (
auto &block : region.getBlocks()) {
117 builder.setInsertionPointToStart(&block);
118 for (
auto &arg : block.getArguments()) {
119 if (isa<hw::ArrayType>(arg.getType()) && hasSpillingUser(arg))
125 for (
auto result : op->getResults()) {
126 if (isa<hw::ArrayType>(result.getType()) && hasSpillingUser(result)) {
127 builder.setInsertionPointAfter(op);
135 assert(isa<LLVM::LLVMArrayType>(arrayValue.getType()) &&
136 "Key is not an LLVM array.");
137 assert(isa<LLVM::LLVMPointerType>(bufferPtr.getType()) &&
138 "Value is not a pointer.");
139 spillMap.insert({arrayValue, bufferPtr});
143 assert(isa<LLVM::LLVMArrayType>(arrayValue.getType()) ||
144 isa<hw::ArrayType>(arrayValue.getType()) &&
"Not an array value");
145 while (isa<LLVM::LLVMArrayType, hw::ArrayType>(arrayValue.getType())) {
146 if (isa<LLVM::LLVMArrayType>(arrayValue.getType())) {
147 auto mapVal =
spillMap.lookup(arrayValue);
151 if (
auto castOp = arrayValue.getDefiningOp<UnrealizedConversionCastOp>())
152 arrayValue = castOp.getOperand(0);
163 assert(isa<LLVM::LLVMArrayType>(llvmArray.getType()) &&
164 "Expected an LLVM array.");
167 LLVM::LoadOp::create(builder, loc, llvmArray.getType(), spillBuffer);
168 map(loadOp.getResult(), spillBuffer);
169 return loadOp.getResult();
177 LLVMTypeConverter &converter,
179 assert(isa<hw::ArrayType>(hwArray.getType()) &&
"Expected an HW array");
180 auto targetType = converter.convertType(hwArray.getType());
182 UnrealizedConversionCastOp::create(builder, loc, targetType, hwArray);
184 auto llvmToHWCast = UnrealizedConversionCastOp::create(
185 builder, loc, hwArray.getType(), spilled);
186 hwArray.replaceAllUsesExcept(llvmToHWCast.getResult(0), hwToLLVMCast);
187 return llvmToHWCast.getResult(0);
193template <
typename SourceOp>
194struct HWArrayOpToLLVMPattern :
public ConvertOpToLLVMPattern<SourceOp> {
196 using ConvertOpToLLVMPattern<SourceOp>::ConvertOpToLLVMPattern;
197 HWArrayOpToLLVMPattern(LLVMTypeConverter &converter,
198 std::optional<HWToLLVMArraySpillCache> &spillCacheOpt)
199 : ConvertOpToLLVMPattern<SourceOp>(converter),
200 spillCacheOpt(spillCacheOpt) {}
203 std::optional<HWToLLVMArraySpillCache> &spillCacheOpt;
216struct StructExplodeOpConversion
217 :
public ConvertOpToLLVMPattern<hw::StructExplodeOp> {
218 using ConvertOpToLLVMPattern<hw::StructExplodeOp>::ConvertOpToLLVMPattern;
221 matchAndRewrite(hw::StructExplodeOp op, OpAdaptor adaptor,
222 ConversionPatternRewriter &rewriter)
const override {
224 SmallVector<Value> replacements;
227 e = cast<LLVM::LLVMStructType>(adaptor.getInput().getType())
232 replacements.push_back(LLVM::ExtractValueOp::create(
233 rewriter, op->getLoc(), adaptor.getInput(),
235 op.getInput().getType(), i)));
237 rewriter.replaceOp(op, replacements);
247struct StructExtractOpConversion
248 :
public ConvertOpToLLVMPattern<hw::StructExtractOp> {
253 ConversionPatternRewriter &rewriter)
const override {
256 op.getInput().getType(), op.getFieldIndex());
257 rewriter.replaceOpWithNewOp<LLVM::ExtractValueOp>(op, adaptor.getInput(),
269struct ArrayInjectOpConversion
270 :
public HWArrayOpToLLVMPattern<hw::ArrayInjectOp> {
271 using HWArrayOpToLLVMPattern<hw::ArrayInjectOp>::HWArrayOpToLLVMPattern;
274 matchAndRewrite(hw::ArrayInjectOp op, OpAdaptor adaptor,
275 ConversionPatternRewriter &rewriter)
const override {
276 auto inputType = cast<hw::ArrayType>(op.getInput().getType());
277 auto oldArrTy = adaptor.getInput().getType();
278 auto newArrTy = oldArrTy;
279 const size_t arrElems = inputType.getNumElements();
282 rewriter.replaceOp(op, adaptor.getInput());
287 LLVM::ConstantOp::create(rewriter, op->getLoc(), rewriter.getI32Type(),
288 rewriter.getI32IntegerAttr(1));
289 auto zextIndex =
zextByOne(op->getLoc(), rewriter, op.getIndex());
292 if (arrElems == 1 || !llvm::isPowerOf2_64(arrElems)) {
297 LLVM::ConstantOp::create(rewriter, op->getLoc(), zextIndex.getType(),
298 rewriter.getI32IntegerAttr(arrElems));
300 LLVM::UMinOp::create(rewriter, op->getLoc(), zextIndex, maxIndex);
302 newArrTy = typeConverter->convertType(
303 hw::ArrayType::get(inputType.getElementType(), arrElems + 1));
304 arrPtr = LLVM::AllocaOp::create(
305 rewriter, op->getLoc(),
306 LLVM::LLVMPointerType::get(rewriter.getContext()), newArrTy, oneC,
309 arrPtr = LLVM::AllocaOp::create(
310 rewriter, op->getLoc(),
311 LLVM::LLVMPointerType::get(rewriter.getContext()), newArrTy, oneC,
315 LLVM::StoreOp::create(rewriter, op->getLoc(), adaptor.getInput(), arrPtr);
317 auto gep = LLVM::GEPOp::create(
318 rewriter, op->getLoc(),
319 LLVM::LLVMPointerType::get(rewriter.getContext()), newArrTy, arrPtr,
320 ArrayRef<LLVM::GEPArg>{0, zextIndex});
322 LLVM::StoreOp::create(rewriter, op->getLoc(), adaptor.getElement(), gep);
324 rewriter.replaceOpWithNewOp<LLVM::LoadOp>(op, oldArrTy, arrPtr);
326 spillCacheOpt->map(loadOp, arrPtr);
336struct ArrayGetOpConversion :
public HWArrayOpToLLVMPattern<hw::ArrayGetOp> {
337 using HWArrayOpToLLVMPattern<
hw::ArrayGetOp>::HWArrayOpToLLVMPattern;
341 ConversionPatternRewriter &rewriter)
const override {
345 arrPtr = spillCacheOpt->lookup(adaptor.getInput());
349 auto arrTy = typeConverter->convertType(op.getInput().getType());
350 auto elemTy = typeConverter->convertType(op.getResult().getType());
351 auto zextIndex =
zextByOne(op->getLoc(), rewriter, op.getIndex());
356 auto gep = LLVM::GEPOp::create(
357 rewriter, op->getLoc(),
358 LLVM::LLVMPointerType::get(rewriter.getContext()), arrTy, arrPtr,
359 ArrayRef<LLVM::GEPArg>{0, zextIndex});
360 rewriter.replaceOpWithNewOp<LLVM::LoadOp>(op, elemTy, gep);
371struct ArraySliceOpConversion
372 :
public HWArrayOpToLLVMPattern<hw::ArraySliceOp> {
377 ConversionPatternRewriter &rewriter)
const override {
379 auto dstTy = typeConverter->convertType(op.getDst().getType());
383 arrPtr = spillCacheOpt->lookup(adaptor.getInput());
387 auto zextIndex =
zextByOne(op->getLoc(), rewriter, op.getLowIndex());
392 auto gep = LLVM::GEPOp::create(
393 rewriter, op->getLoc(),
394 LLVM::LLVMPointerType::get(rewriter.getContext()), dstTy, arrPtr,
395 ArrayRef<LLVM::GEPArg>{0, zextIndex});
397 auto loadOp = rewriter.replaceOpWithNewOp<LLVM::LoadOp>(op, dstTy, gep);
400 spillCacheOpt->map(loadOp, gep);
415struct StructInjectOpConversion
416 :
public ConvertOpToLLVMPattern<hw::StructInjectOp> {
417 using ConvertOpToLLVMPattern<hw::StructInjectOp>::ConvertOpToLLVMPattern;
420 matchAndRewrite(hw::StructInjectOp op, OpAdaptor adaptor,
421 ConversionPatternRewriter &rewriter)
const override {
424 op.getInput().getType(), op.getFieldIndex());
426 rewriter.replaceOpWithNewOp<LLVM::InsertValueOp>(
427 op, adaptor.getInput(), adaptor.getNewValue(), fieldIndex);
440struct ArrayConcatOpConversion
441 :
public HWArrayOpToLLVMPattern<hw::ArrayConcatOp> {
446 ConversionPatternRewriter &rewriter)
const override {
448 hw::ArrayType arrTy = cast<hw::ArrayType>(op.getResult().getType());
449 Type resultTy = typeConverter->convertType(arrTy);
450 auto loc = op.getLoc();
452 Value arr = LLVM::UndefOp::create(rewriter, loc, resultTy);
455 size_t j = op.getInputs().size() - 1, k = 0;
457 for (
size_t i = 0, e = arrTy.getNumElements(); i < e; ++i) {
458 Value element = LLVM::ExtractValueOp::create(rewriter, loc,
459 adaptor.getInputs()[j], k);
460 arr = LLVM::InsertValueOp::create(rewriter, loc, arr, element, i);
464 cast<hw::ArrayType>(op.getInputs()[j].getType()).getNumElements()) {
470 rewriter.replaceOp(op, arr);
474 rewriter.setInsertionPointAfter(arr.getDefiningOp());
476 spillCacheOpt->map(arr, ptr);
492struct BitcastOpConversion :
public ConvertOpToLLVMPattern<hw::BitcastOp> {
493 using ConvertOpToLLVMPattern<
hw::BitcastOp>::ConvertOpToLLVMPattern;
497 ConversionPatternRewriter &rewriter)
const override {
499 Type resultTy = typeConverter->convertType(op.getResult().getType());
501 rewriter.replaceOpWithNewOp<LLVM::LoadOp>(op, resultTy, ptr);
513struct HWConstantOpConversion :
public ConvertToLLVMPattern {
514 explicit HWConstantOpConversion(MLIRContext *ctx,
515 LLVMTypeConverter &typeConverter)
516 : ConvertToLLVMPattern(
hw::ConstantOp::getOperationName(), ctx,
520 matchAndRewrite(Operation *op, ArrayRef<Value> operand,
521 ConversionPatternRewriter &rewriter)
const override {
523 auto constOp = cast<hw::ConstantOp>(op);
525 auto intType = typeConverter->convertType(constOp.getValueAttr().getType());
527 rewriter.replaceOpWithNewOp<LLVM::ConstantOp>(op, intType,
528 constOp.getValueAttr());
538struct HWDynamicArrayCreateOpConversion
539 :
public ConvertOpToLLVMPattern<hw::ArrayCreateOp> {
544 ConversionPatternRewriter &rewriter)
const override {
545 auto arrayTy = typeConverter->convertType(op->getResult(0).getType());
548 Value arr = LLVM::UndefOp::create(rewriter, op->getLoc(), arrayTy);
549 for (
size_t i = 0, e = op.getInputs().size(); i < e; ++i) {
553 op.getResult().getType(), i)];
554 arr = LLVM::InsertValueOp::create(rewriter, op->getLoc(), arr, input, i);
557 rewriter.replaceOp(op, arr);
567class AggregateConstantOpConversion
568 :
public HWArrayOpToLLVMPattern<hw::AggregateConstantOp> {
569 using HWArrayOpToLLVMPattern<hw::AggregateConstantOp>::HWArrayOpToLLVMPattern;
571 bool containsArrayAndStructAggregatesOnly(Type type)
const;
573 bool isMultiDimArrayOfIntegers(Type type,
574 SmallVectorImpl<int64_t> &dims)
const;
576 void flatten(Type type, Attribute attr,
577 SmallVectorImpl<Attribute> &output)
const;
579 Value constructAggregate(OpBuilder &builder,
580 const TypeConverter &typeConverter, Location loc,
581 Type type, Attribute data)
const;
584 explicit AggregateConstantOpConversion(
585 LLVMTypeConverter &typeConverter,
586 DenseMap<std::pair<Type, ArrayAttr>, LLVM::GlobalOp>
587 &constAggregateGlobalsMap,
588 Namespace &globals, std::optional<HWToLLVMArraySpillCache> &spillCacheOpt)
589 : HWArrayOpToLLVMPattern(typeConverter, spillCacheOpt),
590 constAggregateGlobalsMap(constAggregateGlobalsMap), globals(globals) {}
593 matchAndRewrite(hw::AggregateConstantOp op, OpAdaptor adaptor,
594 ConversionPatternRewriter &rewriter)
const override;
597 DenseMap<std::pair<Type, ArrayAttr>, LLVM::GlobalOp>
598 &constAggregateGlobalsMap;
606struct HWStructCreateOpConversion
607 :
public ConvertOpToLLVMPattern<hw::StructCreateOp> {
612 ConversionPatternRewriter &rewriter)
const override {
614 auto resTy = typeConverter->convertType(op.getResult().getType());
616 Value tup = LLVM::UndefOp::create(rewriter, op->getLoc(), resTy);
617 for (
size_t i = 0, e = cast<LLVM::LLVMStructType>(resTy).getBody().size();
621 op.getResult().getType(), i)];
622 tup = LLVM::InsertValueOp::create(rewriter, op->getLoc(), tup, input, i);
625 rewriter.replaceOp(op, tup);
635bool AggregateConstantOpConversion::containsArrayAndStructAggregatesOnly(
637 if (
auto intType = dyn_cast<IntegerType>(type))
640 if (
auto arrTy = dyn_cast<hw::ArrayType>(type))
641 return containsArrayAndStructAggregatesOnly(arrTy.getElementType());
643 if (
auto structTy = dyn_cast<hw::StructType>(type)) {
644 SmallVector<Type> innerTypes;
645 structTy.getInnerTypes(innerTypes);
646 return llvm::all_of(innerTypes, [&](
auto ty) {
647 return containsArrayAndStructAggregatesOnly(ty);
654bool AggregateConstantOpConversion::isMultiDimArrayOfIntegers(
655 Type type, SmallVectorImpl<int64_t> &dims)
const {
656 if (
auto intType = dyn_cast<IntegerType>(type))
659 if (
auto arrTy = dyn_cast<hw::ArrayType>(type)) {
660 dims.push_back(arrTy.getNumElements());
661 return isMultiDimArrayOfIntegers(arrTy.getElementType(), dims);
667void AggregateConstantOpConversion::flatten(
668 Type type, Attribute attr, SmallVectorImpl<Attribute> &output)
const {
669 if (isa<IntegerType>(type)) {
670 assert(isa<IntegerAttr>(attr));
671 output.push_back(attr);
675 auto arrAttr = cast<ArrayAttr>(attr);
676 for (
size_t i = 0, e = arrAttr.size(); i < e; ++i) {
680 flatten(cast<hw::ArrayType>(type).getElementType(), element, output);
684Value AggregateConstantOpConversion::constructAggregate(
685 OpBuilder &builder,
const TypeConverter &typeConverter, Location loc,
686 Type type, Attribute data)
const {
687 Type llvmType = typeConverter.convertType(type);
689 auto getElementType = [](Type type,
size_t index) {
690 if (
auto arrTy = dyn_cast<hw::ArrayType>(type)) {
691 return arrTy.getElementType();
694 assert(isa<hw::StructType>(type));
695 auto structTy = cast<hw::StructType>(type);
696 SmallVector<Type> innerTypes;
697 structTy.getInnerTypes(innerTypes);
698 return innerTypes[index];
701 return TypeSwitch<Type, Value>(type)
702 .Case<IntegerType>([&](
auto ty) {
703 return LLVM::ConstantOp::create(builder, loc, cast<TypedAttr>(data));
705 .Case<hw::ArrayType, hw::StructType>([&](
auto ty) {
706 Value aggVal = LLVM::UndefOp::create(builder, loc, llvmType);
707 auto arrayAttr = cast<ArrayAttr>(data);
708 for (
size_t i = 0, e = arrayAttr.size(); i < e; ++i) {
711 Attribute input = arrayAttr[currIdx];
714 Value element = constructAggregate(builder, typeConverter, loc,
717 LLVM::InsertValueOp::create(builder, loc, aggVal, element, i);
724LogicalResult AggregateConstantOpConversion::matchAndRewrite(
725 hw::AggregateConstantOp op, OpAdaptor adaptor,
726 ConversionPatternRewriter &rewriter)
const {
727 Type aggregateType = op.getResult().getType();
730 if (!containsArrayAndStructAggregatesOnly(aggregateType))
733 auto llvmTy = typeConverter->convertType(op.getResult().getType());
734 auto typeAttrPair = std::make_pair(aggregateType, adaptor.getFields());
736 if (!constAggregateGlobalsMap.count(typeAttrPair) ||
737 !constAggregateGlobalsMap[typeAttrPair]) {
738 auto ipSave = rewriter.saveInsertionPoint();
740 Operation *parent = op->getParentOp();
741 while (!isa<mlir::ModuleOp>(parent->getParentOp())) {
742 parent = parent->getParentOp();
745 rewriter.setInsertionPoint(parent);
748 auto name = globals.newName(
"_aggregate_const_global");
750 SmallVector<int64_t> dims;
751 if (isMultiDimArrayOfIntegers(aggregateType, dims)) {
752 SmallVector<Attribute> ints;
753 flatten(aggregateType, adaptor.getFields(), ints);
755 auto shapedType = RankedTensorType::get(
756 dims, cast<IntegerAttr>(ints.front()).getType());
757 auto denseAttr = DenseElementsAttr::get(shapedType, ints);
759 constAggregateGlobalsMap[typeAttrPair] =
760 LLVM::GlobalOp::create(rewriter, op.getLoc(), llvmTy,
true,
761 LLVM::Linkage::Internal, name, denseAttr);
764 LLVM::GlobalOp::create(rewriter, op.getLoc(), llvmTy,
false,
765 LLVM::Linkage::Internal, name, Attribute());
767 global.getInitializerRegion().push_back(blk);
768 rewriter.setInsertionPointToStart(blk);
771 constructAggregate(rewriter, *typeConverter, op.getLoc(),
772 aggregateType, adaptor.getFields());
773 LLVM::ReturnOp::create(rewriter, op.getLoc(), aggregate);
774 constAggregateGlobalsMap[typeAttrPair] = global;
777 rewriter.restoreInsertionPoint(ipSave);
781 auto addr = LLVM::AddressOfOp::create(rewriter, op->getLoc(),
782 constAggregateGlobalsMap[typeAttrPair]);
783 auto newOp = rewriter.replaceOpWithNewOp<LLVM::LoadOp>(op, llvmTy,
addr);
785 if (spillCacheOpt && llvm::isa<hw::ArrayType>(aggregateType))
786 spillCacheOpt->map(newOp.getResult(),
addr);
796 auto elementTy = converter.convertType(type.getElementType());
797 return LLVM::LLVMArrayType::get(elementTy, type.getNumElements());
801 LLVMTypeConverter &converter) {
802 llvm::SmallVector<Type, 8> elements;
803 mlir::SmallVector<mlir::Type> types;
804 type.getInnerTypes(types);
806 for (
int i = 0, e = types.size(); i < e; ++i)
807 elements.push_back(converter.convertType(
810 return LLVM::LLVMStructType::getLiteral(&converter.getContext(), elements);
818struct HWToLLVMLoweringPass
819 :
public circt::impl::ConvertHWToLLVMBase<HWToLLVMLoweringPass> {
821 using circt::impl::ConvertHWToLLVMBase<
822 HWToLLVMLoweringPass>::ConvertHWToLLVMBase;
824 void runOnOperation()
override;
829 LLVMTypeConverter &converter, RewritePatternSet &
patterns,
831 DenseMap<std::pair<Type, ArrayAttr>, LLVM::GlobalOp>
832 &constAggregateGlobalsMap,
833 std::optional<HWToLLVMArraySpillCache> &spillCacheOpt) {
834 MLIRContext *ctx = converter.getDialect()->getContext();
837 patterns.add<HWConstantOpConversion>(ctx, converter);
838 patterns.add<HWDynamicArrayCreateOpConversion, HWStructCreateOpConversion>(
840 patterns.add<AggregateConstantOpConversion>(
841 converter, constAggregateGlobalsMap, globals, spillCacheOpt);
844 patterns.add<BitcastOpConversion>(converter);
847 patterns.add<StructExplodeOpConversion, StructExtractOpConversion,
848 StructInjectOpConversion>(converter);
850 patterns.add<ArrayGetOpConversion, ArrayInjectOpConversion,
851 ArraySliceOpConversion, ArrayConcatOpConversion>(converter,
856 converter.addConversion(
858 converter.addConversion(
862void HWToLLVMLoweringPass::runOnOperation() {
863 DenseMap<std::pair<Type, ArrayAttr>, LLVM::GlobalOp> constAggregateGlobalsMap;
864 std::optional<HWToLLVMArraySpillCache> spillCacheOpt = {};
870 RewritePatternSet
patterns(&getContext());
871 auto converter = mlir::LLVMTypeConverter(&getContext());
874 if (spillArraysEarly) {
876 OpBuilder spillBuilder(getOperation());
877 spillCacheOpt->spillNonHWOps(spillBuilder, converter, getOperation());
880 LLVMConversionTarget target(getContext());
881 target.addIllegalDialect<hw::HWDialect>();
885 constAggregateGlobalsMap, spillCacheOpt);
888 ConversionConfig config;
889 config.allowPatternRollback =
false;
890 if (failed(applyPartialConversion(getOperation(), target, std::move(
patterns),
assert(baseType &&"element must be base type")
static Type convertStructType(hw::StructType type, LLVMTypeConverter &converter)
static Value zextByOne(Location loc, ConversionPatternRewriter &rewriter, Value value)
Create a zext operation by one bit on the given value.
static Type convertArrayType(hw::ArrayType type, LLVMTypeConverter &converter)
static Value spillValueOnStack(OpBuilder &builder, Location loc, Value spillVal)
A namespace that is used to store existing names and generate new names in some scope within the IR.
void add(mlir::ModuleOp module)
void addDefinitions(mlir::Operation *top)
Populate the symbol cache with all symbol-defining operations within the 'top' operation.
Default symbol cache implementation; stores associations between names (StringAttr's) to mlir::Operat...
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
void populateHWToLLVMTypeConversions(mlir::LLVMTypeConverter &converter)
Get the HW to LLVM type conversions.
void populateHWToLLVMConversionPatterns(mlir::LLVMTypeConverter &converter, RewritePatternSet &patterns, Namespace &globals, DenseMap< std::pair< Type, ArrayAttr >, mlir::LLVM::GlobalOp > &constAggregateGlobalsMap, std::optional< HWToLLVMArraySpillCache > &spillCacheOpt)
Get the HW to LLVM conversion patterns.
Helper class mapping array values (HW or LLVM Dialect) to pointers to buffers containing the array va...
Value spillHWArrayValue(OpBuilder &builder, Location loc, mlir::LLVMTypeConverter &converter, Value hwArray)
Value lookup(Value arrayValue)
Retrieve a pointer to a buffer containing the given array value (HW or LLVM Dialect).
void spillNonHWOps(mlir::OpBuilder &builder, mlir::LLVMTypeConverter &converter, Operation *containerOp)
Spill HW array values produced by 'foreign' dialects on the stack.
void map(mlir::Value arrayValue, mlir::Value bufferPtr)
Map an LLVM array value to an LLVM pointer.
Value spillLLVMArrayValue(OpBuilder &builder, Location loc, Value llvmArray)
llvm::DenseMap< Value, Value > spillMap
static uint32_t convertToLLVMEndianess(Type type, uint32_t index)
Convert an index into a HW ArrayType or StructType to LLVM Endianess.
static uint32_t llvmIndexOfStructField(hw::StructType type, StringRef fieldName)
Get the index of a specific StructType field in the LLVM lowering of the StructType.