================ @@ -0,0 +1,346 @@ +//==- CXXABILowering.cpp - lower C++ operations to target-specific ABI form -=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "PassDetail.h" +#include "TargetLowering/LowerModule.h" + +#include "mlir/IR/PatternMatch.h" +#include "mlir/Interfaces/DataLayoutInterfaces.h" +#include "mlir/Pass/Pass.h" +#include "mlir/Transforms/DialectConversion.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/CIR/Dialect/Builder/CIRBaseBuilder.h" +#include "clang/CIR/Dialect/IR/CIRAttrs.h" +#include "clang/CIR/Dialect/IR/CIRDialect.h" +#include "clang/CIR/Dialect/IR/CIROpsEnums.h" +#include "clang/CIR/Dialect/Passes.h" +#include "clang/CIR/MissingFeatures.h" + +using namespace mlir; +using namespace cir; + +namespace mlir { +#define GEN_PASS_DEF_CXXABILOWERING +#include "clang/CIR/Dialect/Passes.h.inc" +} // namespace mlir + +namespace { + +template <typename Op> +class CIROpCXXABILoweringPattern : public mlir::OpConversionPattern<Op> { +protected: + mlir::DataLayout *dataLayout; + cir::LowerModule *lowerModule; + +public: + CIROpCXXABILoweringPattern(mlir::MLIRContext *context, + const mlir::TypeConverter &typeConverter, + mlir::DataLayout &dataLayout, + cir::LowerModule &lowerModule) + : mlir::OpConversionPattern<Op>(typeConverter, context), + dataLayout(&dataLayout), lowerModule(&lowerModule) {} +}; + +#define CIR_CXXABI_LOWERING_PATTERN(name, operation) \ + struct name : CIROpCXXABILoweringPattern<operation> { \ + using CIROpCXXABILoweringPattern<operation>::CIROpCXXABILoweringPattern; \ + \ + mlir::LogicalResult \ + matchAndRewrite(operation op, OpAdaptor adaptor, \ + mlir::ConversionPatternRewriter &rewriter) const override; \ + } + +CIR_CXXABI_LOWERING_PATTERN(CIRAllocaOpABILowering, cir::AllocaOp); +CIR_CXXABI_LOWERING_PATTERN(CIRConstantOpABILowering, cir::ConstantOp); +CIR_CXXABI_LOWERING_PATTERN(CIRFuncOpABILowering, cir::FuncOp); +CIR_CXXABI_LOWERING_PATTERN(CIRGetRuntimeMemberOpABILowering, + cir::GetRuntimeMemberOp); +CIR_CXXABI_LOWERING_PATTERN(CIRGlobalOpABILowering, cir::GlobalOp); +#undef CIR_CXXABI_LOWERING_PATTERN + +struct CXXABILoweringPass + : public impl::CXXABILoweringBase<CXXABILoweringPass> { + CXXABILoweringPass() = default; + void runOnOperation() override; +}; + +/// A generic ABI lowering rewrite pattern. This conversion pattern matches any +/// CIR dialect operations with at least one operand or result of an +/// ABI-dependent type. This conversion pattern rewrites the matched operation +/// by replacing all its ABI-dependent operands and results with their +/// lowered counterparts. +class CIRGenericCXXABILoweringPattern : public mlir::ConversionPattern { +public: + CIRGenericCXXABILoweringPattern(mlir::MLIRContext *context, + const mlir::TypeConverter &typeConverter) + : mlir::ConversionPattern(typeConverter, MatchAnyOpTypeTag(), + /*benefit=*/1, context) {} + + mlir::LogicalResult + matchAndRewrite(mlir::Operation *op, llvm::ArrayRef<mlir::Value> operands, + mlir::ConversionPatternRewriter &rewriter) const override { + // Do not match on operations that have dedicated ABI lowering rewrite rules + if (llvm::isa<cir::AllocaOp, cir::ConstantOp, cir::FuncOp, + cir::GetRuntimeMemberOp, cir::GlobalOp>(op)) + return mlir::failure(); + + const mlir::TypeConverter *typeConverter = getTypeConverter(); + assert(typeConverter && + "CIRGenericCXXABILoweringPattern requires a type converter"); + if (typeConverter->isLegal(op)) { + // The operation does not have any CXXABI-dependent operands or results, + // the match fails. + return mlir::failure(); + } + + assert(op->getNumRegions() == 0 && "CIRGenericCXXABILoweringPattern cannot " + "deal with operations with regions"); + + mlir::OperationState loweredOpState(op->getLoc(), op->getName()); + loweredOpState.addOperands(operands); + loweredOpState.addAttributes(op->getAttrs()); + loweredOpState.addSuccessors(op->getSuccessors()); + + // Lower all result types + llvm::SmallVector<mlir::Type> loweredResultTypes; + loweredResultTypes.reserve(op->getNumResults()); + for (mlir::Type result : op->getResultTypes()) + loweredResultTypes.push_back(typeConverter->convertType(result)); + loweredOpState.addTypes(loweredResultTypes); + + // Clone the operation with lowered operand types and result types + mlir::Operation *loweredOp = rewriter.create(loweredOpState); + + rewriter.replaceOp(op, loweredOp); + return mlir::success(); + } +}; + +} // namespace + +mlir::LogicalResult CIRAllocaOpABILowering::matchAndRewrite( + cir::AllocaOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + mlir::Type allocaPtrTy = op.getType(); + mlir::Type allocaTy = op.getAllocaType(); + mlir::Type loweredAllocaPtrTy = getTypeConverter()->convertType(allocaPtrTy); + mlir::Type loweredAllocaTy = getTypeConverter()->convertType(allocaTy); + + cir::AllocaOp loweredOp = cir::AllocaOp::create( + rewriter, op.getLoc(), loweredAllocaPtrTy, loweredAllocaTy, op.getName(), + op.getAlignmentAttr(), /*dynAllocSize=*/adaptor.getDynAllocSize()); + loweredOp.setInit(op.getInit()); + loweredOp.setConstant(op.getConstant()); + loweredOp.setAnnotationsAttr(op.getAnnotationsAttr()); + + rewriter.replaceOp(op, loweredOp); + return mlir::success(); +} + +mlir::LogicalResult CIRConstantOpABILowering::matchAndRewrite( + cir::ConstantOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + + if (mlir::isa<cir::DataMemberType>(op.getType())) { + auto dataMember = mlir::cast<cir::DataMemberAttr>(op.getValue()); + mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>()); + mlir::TypedAttr abiValue = lowerModule->getCXXABI().lowerDataMemberConstant( + dataMember, layout, *getTypeConverter()); + rewriter.replaceOpWithNewOp<ConstantOp>(op, abiValue); + return mlir::success(); + } + + llvm_unreachable("constant operand is not an CXXABI-dependent type"); +} + +mlir::LogicalResult CIRFuncOpABILowering::matchAndRewrite( + cir::FuncOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + cir::FuncType opFuncType = op.getFunctionType(); + mlir::TypeConverter::SignatureConversion signatureConversion( + opFuncType.getNumInputs()); + + for (const auto &[i, argType] : llvm::enumerate(opFuncType.getInputs())) { + mlir::Type loweredArgType = getTypeConverter()->convertType(argType); + if (!loweredArgType) + return mlir::failure(); + signatureConversion.addInputs(i, loweredArgType); + } + + mlir::Type loweredResultType = + getTypeConverter()->convertType(opFuncType.getReturnType()); + if (!loweredResultType) + return mlir::failure(); + + auto loweredFuncType = + cir::FuncType::get(signatureConversion.getConvertedTypes(), + loweredResultType, /*isVarArg=*/opFuncType.isVarArg()); + + // Create a new cir.func operation for the CXXABI-lowered function. + cir::FuncOp loweredFuncOp = rewriter.cloneWithoutRegions(op); + loweredFuncOp.setFunctionType(loweredFuncType); + rewriter.inlineRegionBefore(op.getBody(), loweredFuncOp.getBody(), + loweredFuncOp.end()); + if (mlir::failed(rewriter.convertRegionTypes( + &loweredFuncOp.getBody(), *getTypeConverter(), &signatureConversion))) + return mlir::failure(); + + rewriter.eraseOp(op); + return mlir::success(); +} + +mlir::LogicalResult CIRGlobalOpABILowering::matchAndRewrite( + cir::GlobalOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + mlir::Type ty = op.getSymType(); + mlir::Type loweredTy = getTypeConverter()->convertType(ty); + if (!loweredTy) + return mlir::failure(); + + mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>()); + + mlir::Attribute loweredInit; + if (mlir::isa<cir::DataMemberType>(ty)) { + cir::DataMemberAttr init = + mlir::cast_if_present<cir::DataMemberAttr>(op.getInitialValueAttr()); + loweredInit = lowerModule->getCXXABI().lowerDataMemberConstant( + init, layout, *getTypeConverter()); + } else { + llvm_unreachable( + "inputs to cir.global in ABI lowering must be data member or method"); + } ---------------- Lancern wrote:
Handling for `cir::MethodType` is missing here? https://github.com/llvm/llvm-project/pull/172133 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
