[clang] [CIR] Move CIR CXXABI lowering to a standlone pass (PR #172133)
Sirui Mu via cfe-commits
cfe-commits at lists.llvm.org
Mon Dec 15 04:58:47 PST 2025
================
@@ -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
More information about the cfe-commits
mailing list