From 57f037d2ee8747285433e557462b924398d24634 Mon Sep 17 00:00:00 2001 From: Sirui Mu Date: Wed, 12 Mar 2025 22:25:42 +0800 Subject: [PATCH] [CIR][WIP] Add ABI lowering pass This patch adds a new pass cir-abi-lowering to the CIR dialect. This pass runs before the CallConvLowering pass, and it expands all ABI-dependent types and operations inside a function to their ABI-independent equivalences according to the ABI specification. This patch also moves the lowering code of the following types and operations from the LLVM lowering conversion to the new pass: - The pointer-to-data-member type `cir.data_member`; - The pointer-to-member-function type `cir.method`; - All operations working on operands of the above types. --- clang/include/clang/CIR/Dialect/Passes.h | 3 + clang/include/clang/CIR/Dialect/Passes.td | 21 + clang/lib/CIR/CodeGen/CIRPasses.cpp | 1 + .../CIR/Dialect/Transforms/ABILowering.cpp | 474 ++++++++++++++++++ .../lib/CIR/Dialect/Transforms/CMakeLists.txt | 1 + .../Transforms/TargetLowering/CIRCXXABI.h | 14 +- .../TargetLowering/ItaniumCXXABI.cpp | 35 +- .../Transforms/TargetLowering/LowerModule.cpp | 6 + .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 167 +----- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h | 116 +---- .../test/CIR/Transforms/ABILowering/cast.cir | 53 ++ clang/test/CIR/Transforms/ABILowering/cmp.cir | 41 ++ .../test/CIR/Transforms/ABILowering/const.cir | 40 ++ .../test/CIR/Transforms/ABILowering/func.cir | 28 ++ .../CIR/Transforms/ABILowering/global.cir | 22 + .../CIR/Transforms/ABILowering/member-ptr.cir | 106 ++++ clang/tools/cir-opt/cir-opt.cpp | 4 + 17 files changed, 829 insertions(+), 303 deletions(-) create mode 100644 clang/lib/CIR/Dialect/Transforms/ABILowering.cpp create mode 100644 clang/test/CIR/Transforms/ABILowering/cast.cir create mode 100644 clang/test/CIR/Transforms/ABILowering/cmp.cir create mode 100644 clang/test/CIR/Transforms/ABILowering/const.cir create mode 100644 clang/test/CIR/Transforms/ABILowering/func.cir create mode 100644 clang/test/CIR/Transforms/ABILowering/global.cir create mode 100644 clang/test/CIR/Transforms/ABILowering/member-ptr.cir diff --git a/clang/include/clang/CIR/Dialect/Passes.h b/clang/include/clang/CIR/Dialect/Passes.h index d6cd4831a6af..d877357c3c29 100644 --- a/clang/include/clang/CIR/Dialect/Passes.h +++ b/clang/include/clang/CIR/Dialect/Passes.h @@ -40,6 +40,9 @@ std::unique_ptr createFlattenCFGPass(); std::unique_ptr createHoistAllocasPass(); std::unique_ptr createGotoSolverPass(); +/// Create a pass to expand ABI-dependent types and operations. +std::unique_ptr createABILoweringPass(); + /// Create a pass to lower ABI-independent function definitions/calls. std::unique_ptr createCallConvLoweringPass(); diff --git a/clang/include/clang/CIR/Dialect/Passes.td b/clang/include/clang/CIR/Dialect/Passes.td index c2fac40b0f0f..a82f7beb86d6 100644 --- a/clang/include/clang/CIR/Dialect/Passes.td +++ b/clang/include/clang/CIR/Dialect/Passes.td @@ -180,6 +180,27 @@ def LibOpt : Pass<"cir-lib-opt"> { ]; } +def ABILowering : Pass<"cir-abi-lowering"> { + let summary = "Expands ABI-dependent types and operations"; + let description = [{ + This pass expands ABI-dependent CIR types and operations to more "primitive" + ABI-independent CIR types and operations according to the target ABI + specification. + + Some CIR types, such as pointers to members, may have different layouts and + representations under different target ABIs. This pass expands these types + to their underlying representations as specified by the target ABI. For + example, when targeting Itanium ABI, this pass will replace pointers to + member functions with a struct with two ptrdiff_t fields. + + Similarly, some CIR operations may also behave differently under different + target ABIs. This pass also expands these operations to more "primitive" + CIR operations as specified by the target ABI. + }]; + let constructor = "mlir::createABILoweringPass()"; + let dependentDialects = ["cir::CIRDialect"]; +} + def CallConvLowering : Pass<"cir-call-conv-lowering"> { let summary = "Handle calling conventions for CIR functions"; let description = [{ diff --git a/clang/lib/CIR/CodeGen/CIRPasses.cpp b/clang/lib/CIR/CodeGen/CIRPasses.cpp index 9fc51e29bd64..2793975bf54f 100644 --- a/clang/lib/CIR/CodeGen/CIRPasses.cpp +++ b/clang/lib/CIR/CodeGen/CIRPasses.cpp @@ -97,6 +97,7 @@ mlir::LogicalResult runCIRToCIRPasses( namespace mlir { void populateCIRPreLoweringPasses(OpPassManager &pm, bool useCCLowering) { + pm.addPass(createABILoweringPass()); if (useCCLowering) pm.addPass(createCallConvLoweringPass()); pm.addPass(createHoistAllocasPass()); diff --git a/clang/lib/CIR/Dialect/Transforms/ABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/ABILowering.cpp new file mode 100644 index 000000000000..b5d3996f4ce6 --- /dev/null +++ b/clang/lib/CIR/Dialect/Transforms/ABILowering.cpp @@ -0,0 +1,474 @@ +//===- ABILowering.cpp - Expands ABI-dependent types and operations -------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file implements the CIR ABI lowering pass which expands ABI-dependent +// types and operations to equivalent ABI-independent types and operations. +// +//===----------------------------------------------------------------------===// + +#include "TargetLowering/LowerModule.h" +#include "mlir/IR/BuiltinOps.h" +#include "mlir/IR/PatternMatch.h" +#include "mlir/Interfaces/DataLayoutInterfaces.h" +#include "mlir/Pass/Pass.h" +#include "mlir/Transforms/DialectConversion.h" +#include "clang/CIR/Dialect/IR/CIRDialect.h" +#include "clang/CIR/Dialect/Passes.h" + +#define GEN_PASS_DEF_ABILOWERING +#include "clang/CIR/Dialect/Passes.h.inc" + +namespace cir { +namespace { + +template +class CIROpABILoweringPattern : public mlir::OpConversionPattern { +protected: + mlir::DataLayout *dataLayout; + cir::LowerModule *lowerModule; + +public: + CIROpABILoweringPattern(mlir::MLIRContext *context, + const mlir::TypeConverter &typeConverter, + mlir::DataLayout &dataLayout, + cir::LowerModule &lowerModule) + : mlir::OpConversionPattern(typeConverter, context), + dataLayout(&dataLayout), lowerModule(&lowerModule) {} +}; + +#define CIR_ABI_LOWERING_PATTERN(name, operation) \ + struct name : CIROpABILoweringPattern { \ + using CIROpABILoweringPattern::CIROpABILoweringPattern; \ + \ + mlir::LogicalResult \ + matchAndRewrite(operation op, OpAdaptor adaptor, \ + mlir::ConversionPatternRewriter &rewriter) const override; \ + } +CIR_ABI_LOWERING_PATTERN(CIRAllocaOpABILowering, cir::AllocaOp); +CIR_ABI_LOWERING_PATTERN(CIRBaseDataMemberOpABILowering, cir::BaseDataMemberOp); +CIR_ABI_LOWERING_PATTERN(CIRBaseMethodOpABILowering, cir::BaseMethodOp); +CIR_ABI_LOWERING_PATTERN(CIRCastOpABILowering, cir::CastOp); +CIR_ABI_LOWERING_PATTERN(CIRCmpOpABILowering, cir::CmpOp); +CIR_ABI_LOWERING_PATTERN(CIRConstantOpABILowering, cir::ConstantOp); +CIR_ABI_LOWERING_PATTERN(CIRDerivedDataMemberOpABILowering, + cir::DerivedDataMemberOp); +CIR_ABI_LOWERING_PATTERN(CIRDerivedMethodOpABILowering, cir::DerivedMethodOp); +CIR_ABI_LOWERING_PATTERN(CIRFuncOpABILowering, cir::FuncOp); +CIR_ABI_LOWERING_PATTERN(CIRGetMethodOpABILowering, cir::GetMethodOp); +CIR_ABI_LOWERING_PATTERN(CIRGetRuntimeMemberOpABILowering, + cir::GetRuntimeMemberOp); +CIR_ABI_LOWERING_PATTERN(CIRGlobalOpABILowering, cir::GlobalOp); +#undef CIR_ABI_LOWERING_PATTERN + +/// 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 CIRGenericABILoweringPattern : public mlir::ConversionPattern { +public: + CIRGenericABILoweringPattern(mlir::MLIRContext *context, + const mlir::TypeConverter &typeConverter) + : mlir::ConversionPattern(typeConverter, MatchAnyOpTypeTag(), + /*benefit=*/1, context) {} + + mlir::LogicalResult + matchAndRewrite(mlir::Operation *op, llvm::ArrayRef operands, + mlir::ConversionPatternRewriter &rewriter) const override { + // Do not match on operations that have dedicated ABI lowering rewrite rules + if (llvm::isa(op)) + return mlir::failure(); + + const mlir::TypeConverter *typeConverter = getTypeConverter(); + assert(typeConverter && + "CIRGenericABILoweringPattern requires a type converter"); + if (typeConverter->isLegal(op)) { + // The operation does not have any ABI-dependent operands or results, the + // match fails. + return mlir::failure(); + } + + assert(op->getNumRegions() == 0 && "CIRGenericABILoweringPattern 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 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(); + } +}; + +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 = rewriter.create( + 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 CIRBaseDataMemberOpABILowering::matchAndRewrite( + cir::BaseDataMemberOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + mlir::Value loweredResult = lowerModule->getCXXABI().lowerBaseDataMember( + op, adaptor.getSrc(), rewriter); + rewriter.replaceOp(op, loweredResult); + return mlir::success(); +} + +mlir::LogicalResult CIRBaseMethodOpABILowering::matchAndRewrite( + cir::BaseMethodOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + mlir::Value loweredResult = + lowerModule->getCXXABI().lowerBaseMethod(op, adaptor.getSrc(), rewriter); + rewriter.replaceOp(op, loweredResult); + return mlir::success(); +} + +mlir::LogicalResult CIRCastOpABILowering::matchAndRewrite( + cir::CastOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + mlir::Type srcTy = op.getSrc().getType(); + assert((mlir::isa(srcTy)) && + "input to bitcast in ABI lowering must be a data member or method"); + + switch (op.getKind()) { + case cir::CastKind::bitcast: { + mlir::Type destTy = getTypeConverter()->convertType(op.getType()); + mlir::Value loweredResult; + if (mlir::isa(srcTy)) + loweredResult = lowerModule->getCXXABI().lowerDataMemberBitcast( + op, destTy, adaptor.getSrc(), rewriter); + else + loweredResult = lowerModule->getCXXABI().lowerMethodBitcast( + op, destTy, adaptor.getSrc(), rewriter); + rewriter.replaceOp(op, loweredResult); + return mlir::success(); + } + case cir::CastKind::member_ptr_to_bool: { + mlir::Value loweredResult; + if (mlir::isa(srcTy)) + loweredResult = lowerModule->getCXXABI().lowerMethodToBoolCast( + op, adaptor.getSrc(), rewriter); + else + loweredResult = lowerModule->getCXXABI().lowerDataMemberToBoolCast( + op, adaptor.getSrc(), rewriter); + rewriter.replaceOp(op, loweredResult); + return mlir::success(); + } + default: + break; + } + + return mlir::failure(); +} + +mlir::LogicalResult CIRCmpOpABILowering::matchAndRewrite( + cir::CmpOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + auto type = op.getLhs().getType(); + assert((mlir::isa(type)) && + "input to cmp in ABI lowering must be a data member or method"); + + mlir::Value loweredResult; + if (mlir::isa(type)) + loweredResult = lowerModule->getCXXABI().lowerDataMemberCmp( + op, adaptor.getLhs(), adaptor.getRhs(), rewriter); + else + loweredResult = lowerModule->getCXXABI().lowerMethodCmp( + op, adaptor.getLhs(), adaptor.getRhs(), rewriter); + + rewriter.replaceOp(op, loweredResult); + return mlir::success(); +} + +mlir::LogicalResult CIRConstantOpABILowering::matchAndRewrite( + cir::ConstantOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + + if (mlir::isa(op.getType())) { + auto dataMember = mlir::cast(op.getValue()); + mlir::DataLayout layout(op->getParentOfType()); + mlir::TypedAttr abiValue = lowerModule->getCXXABI().lowerDataMemberConstant( + dataMember, layout, *getTypeConverter()); + rewriter.replaceOpWithNewOp(op, abiValue); + return mlir::success(); + } + + if (mlir::isa(op.getType())) { + auto method = mlir::cast(op.getValue()); + mlir::DataLayout layout(op->getParentOfType()); + mlir::TypedAttr abiValue = lowerModule->getCXXABI().lowerMethodConstant( + method, layout, *getTypeConverter()); + rewriter.replaceOpWithNewOp(op, abiValue); + return mlir::success(); + } + + llvm_unreachable("constant operand is not an ABI-dependent type"); +} + +mlir::LogicalResult CIRDerivedDataMemberOpABILowering::matchAndRewrite( + cir::DerivedDataMemberOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + mlir::Value loweredResult = lowerModule->getCXXABI().lowerDerivedDataMember( + op, adaptor.getSrc(), rewriter); + rewriter.replaceOp(op, loweredResult); + return mlir::success(); +} + +mlir::LogicalResult CIRDerivedMethodOpABILowering::matchAndRewrite( + cir::DerivedMethodOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + mlir::Value loweredResult = lowerModule->getCXXABI().lowerDerivedMethod( + op, adaptor.getSrc(), rewriter); + rewriter.replaceOp(op, loweredResult); + return mlir::success(); +} + +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 ABI-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 CIRGetMethodOpABILowering::matchAndRewrite( + cir::GetMethodOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + mlir::Value loweredResults[2]; + lowerModule->getCXXABI().lowerGetMethod( + op, loweredResults, adaptor.getMethod(), adaptor.getObject(), rewriter); + rewriter.replaceOp(op, loweredResults); + return mlir::success(); +} + +mlir::LogicalResult CIRGetRuntimeMemberOpABILowering::matchAndRewrite( + cir::GetRuntimeMemberOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + mlir::Type resTy = getTypeConverter()->convertType(op.getType()); + mlir::Operation *llvmOp = lowerModule->getCXXABI().lowerGetRuntimeMember( + op, resTy, adaptor.getAddr(), adaptor.getMember(), rewriter); + rewriter.replaceOp(op, llvmOp); + 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::Attribute loweredInit; + if (mlir::isa(ty)) { + cir::DataMemberAttr init = + mlir::cast_if_present(op.getInitialValueAttr()); + loweredInit = lowerModule->getCXXABI().lowerDataMemberConstant( + init, layout, *getTypeConverter()); + } else if (mlir::isa(ty)) { + cir::MethodAttr init = + mlir::cast_if_present(op.getInitialValueAttr()); + loweredInit = lowerModule->getCXXABI().lowerMethodConstant( + init, layout, *getTypeConverter()); + } else { + llvm_unreachable( + "inputs to cir.global in ABI lowering must be data member or method"); + } + + auto abiOp = mlir::cast(rewriter.clone(*op.getOperation())); + abiOp.setInitialValueAttr(loweredInit); + abiOp.setSymType(loweredTy); + rewriter.replaceOp(op, abiOp); + return mlir::success(); +} + +static void prepareABITypeConverter(mlir::TypeConverter &converter, + mlir::DataLayout &dataLayout, + cir::LowerModule &lowerModule) { + converter.addConversion([&](mlir::Type type) -> mlir::Type { return type; }); + converter.addConversion([&](cir::PointerType type) -> mlir::Type { + mlir::Type loweredPointeeType = converter.convertType(type.getPointee()); + if (!loweredPointeeType) + return {}; + return cir::PointerType::get(type.getContext(), loweredPointeeType, + type.getAddrSpace()); + }); + converter.addConversion([&](cir::DataMemberType type) -> mlir::Type { + mlir::Type abiType = lowerModule.getCXXABI().getDataMemberABIType(); + return converter.convertType(abiType); + }); + converter.addConversion([&](cir::MethodType type) -> mlir::Type { + mlir::Type abiType = lowerModule.getCXXABI().getMethodABIType(); + return converter.convertType(abiType); + }); + converter.addConversion([&](cir::FuncType type) -> mlir::Type { + llvm::SmallVector loweredInputTypes; + loweredInputTypes.reserve(type.getNumInputs()); + if (mlir::failed( + converter.convertTypes(type.getInputs(), loweredInputTypes))) + return {}; + + mlir::Type loweredReturnType = converter.convertType(type.getReturnType()); + if (!loweredReturnType) + return {}; + + return cir::FuncType::get(loweredInputTypes, loweredReturnType, + /*isVarArg=*/type.getVarArg()); + }); +} + +static void +populateABIConversionTarget(mlir::ConversionTarget &target, + const mlir::TypeConverter &typeConverter) { + target.addLegalOp(); + + // The ABI lowering pass is interested in CIR operations with operands or + // results of ABI-dependent types, or CIR operations with regions whose block + // arguments are of ABI-dependent types. + target.addDynamicallyLegalDialect( + [&typeConverter](mlir::Operation *op) { + if (!typeConverter.isLegal(op)) + return false; + return std::all_of(op->getRegions().begin(), op->getRegions().end(), + [&typeConverter](mlir::Region ®ion) { + return typeConverter.isLegal(®ion); + }); + }); + + // Some CIR ops needs special checking for legality + target.addDynamicallyLegalOp([&typeConverter](cir::FuncOp op) { + return typeConverter.isLegal(op.getFunctionType()); + }); + target.addDynamicallyLegalOp( + [&typeConverter](cir::GlobalOp op) { + return typeConverter.isLegal(op.getSymType()); + }); +} + +//===----------------------------------------------------------------------===// +// The Pass +//===----------------------------------------------------------------------===// + +struct ABILoweringPass : ::impl::ABILoweringBase { + using ABILoweringBase::ABILoweringBase; + + void runOnOperation() override; + llvm::StringRef getArgument() const override { return "cir-abi-lowering"; }; +}; + +void ABILoweringPass::runOnOperation() { + auto module = mlir::cast(getOperation()); + mlir::MLIRContext *ctx = module.getContext(); + + // If the triple is not present, e.g. CIR modules parsed from text, we + // cannot init LowerModule properly. + assert(!cir::MissingFeatures::makeTripleAlwaysPresent()); + if (!module->hasAttr(cir::CIRDialect::getTripleAttrName())) { + // If no target triple is available, skip the ABI lowering pass. + return; + } + + mlir::PatternRewriter rewriter(ctx); + std::unique_ptr lowerModule = + cir::createLowerModule(module, rewriter); + + mlir::DataLayout dataLayout(module); + mlir::TypeConverter typeConverter; + prepareABITypeConverter(typeConverter, dataLayout, *lowerModule); + + mlir::RewritePatternSet patterns(ctx); + patterns.add(patterns.getContext(), + typeConverter); + patterns.add< + // clang-format off + CIRAllocaOpABILowering, + CIRBaseDataMemberOpABILowering, + CIRBaseMethodOpABILowering, + CIRCastOpABILowering, + CIRCmpOpABILowering, + CIRConstantOpABILowering, + CIRDerivedDataMemberOpABILowering, + CIRDerivedMethodOpABILowering, + CIRFuncOpABILowering, + CIRGetMethodOpABILowering, + CIRGetRuntimeMemberOpABILowering, + CIRGlobalOpABILowering + // clang-format on + >(patterns.getContext(), typeConverter, dataLayout, *lowerModule); + + mlir::ConversionTarget target(*ctx); + populateABIConversionTarget(target, typeConverter); + + if (failed(mlir::applyPartialConversion(module, target, std::move(patterns)))) + signalPassFailure(); +} + +} // namespace +} // namespace cir + +std::unique_ptr mlir::createABILoweringPass() { + return std::make_unique(); +} diff --git a/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt b/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt index 76ac0cbf1c8d..786d57b01d2d 100644 --- a/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt +++ b/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt @@ -12,6 +12,7 @@ add_clang_library(MLIRCIRTransforms FlattenCFG.cpp GotoSolver.cpp SCFPrepare.cpp + ABILowering.cpp CallConvLowering.cpp HoistAllocas.cpp diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h b/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h index ec62ed1dbacf..024b45c1610c 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h @@ -66,17 +66,11 @@ class CIRCXXABI { /// FIXME(cir): This expects a CXXRecordDecl! Not any record type. virtual RecordArgABI getRecordArgABI(const RecordType RD) const = 0; - /// Lower the given data member pointer type to its ABI type. The returned - /// type is also a CIR type. - virtual mlir::Type - lowerDataMemberType(cir::DataMemberType type, - const mlir::TypeConverter &typeConverter) const = 0; + /// Get the ABI type for a pointer to data member. + virtual mlir::Type getDataMemberABIType() const = 0; - /// Lower the given member function pointer type to its ABI type. The returned - /// type is also a CIR type. - virtual mlir::Type - lowerMethodType(cir::MethodType type, - const mlir::TypeConverter &typeConverter) const = 0; + /// Get the ABI type for a pointer to member function. + virtual mlir::Type getMethodABIType() const = 0; /// Lower the given data member pointer constant to a constant of the ABI /// type. The returned constant is represented as an attribute as well. diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/ItaniumCXXABI.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/ItaniumCXXABI.cpp index 17ff1433bf4a..3ae7febfb209 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/ItaniumCXXABI.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/ItaniumCXXABI.cpp @@ -66,13 +66,9 @@ class ItaniumCXXABI : public CIRCXXABI { return RAA_Default; } - mlir::Type - lowerDataMemberType(cir::DataMemberType type, - const mlir::TypeConverter &typeConverter) const override; + mlir::Type getDataMemberABIType() const override; - mlir::Type - lowerMethodType(cir::MethodType type, - const mlir::TypeConverter &typeConverter) const override; + mlir::Type getMethodABIType() const override; mlir::TypedAttr lowerDataMemberConstant( cir::DataMemberAttr attr, const mlir::DataLayout &layout, @@ -153,17 +149,14 @@ static cir::IntType getPtrDiffCIRTy(LowerModule &lowerMod) { target.isTypeSigned(ptrdiffTy)); } -mlir::Type ItaniumCXXABI::lowerDataMemberType( - cir::DataMemberType type, const mlir::TypeConverter &typeConverter) const { +mlir::Type ItaniumCXXABI::getDataMemberABIType() const { // Itanium C++ ABI 2.3.1: // A data member pointer is represented as the data member's offset in bytes // from the address point of an object of the base type, as a ptrdiff_t. return getPtrDiffCIRTy(LM); } -mlir::Type -ItaniumCXXABI::lowerMethodType(cir::MethodType type, - const mlir::TypeConverter &typeConverter) const { +mlir::Type ItaniumCXXABI::getMethodABIType() const { // Itanium C++ ABI 2.3.2: // In all representations, the basic ABI properties of member function // pointer types are those of the following class, where fnptr_t is the @@ -178,16 +171,16 @@ ItaniumCXXABI::lowerMethodType(cir::MethodType type, // Note that clang CodeGen emits struct{ptrdiff_t, ptrdiff_t} for member // function pointers. Let's follow this approach. - return cir::RecordType::get(type.getContext(), {ptrdiffCIRTy, ptrdiffCIRTy}, - /*packed=*/false, /*padded=*/false, - cir::RecordType::Struct); + return cir::RecordType::get( + ptrdiffCIRTy.getContext(), {ptrdiffCIRTy, ptrdiffCIRTy}, + /*packed=*/false, /*padded=*/false, cir::RecordType::Struct); } mlir::TypedAttr ItaniumCXXABI::lowerDataMemberConstant( cir::DataMemberAttr attr, const mlir::DataLayout &layout, const mlir::TypeConverter &typeConverter) const { uint64_t memberOffset; - if (attr.isNullPtr()) { + if (!attr || attr.isNullPtr()) { // Itanium C++ ABI 2.3: // A NULL pointer is represented as -1. memberOffset = -1ull; @@ -200,7 +193,7 @@ mlir::TypedAttr ItaniumCXXABI::lowerDataMemberConstant( attr.getType().getClsTy().getElementOffset(layout, memberIndex); } - mlir::Type abiTy = lowerDataMemberType(attr.getType(), typeConverter); + mlir::Type abiTy = getDataMemberABIType(); return cir::IntAttr::get(abiTy, memberOffset); } @@ -208,8 +201,7 @@ mlir::TypedAttr ItaniumCXXABI::lowerMethodConstant( cir::MethodAttr attr, const mlir::DataLayout &layout, const mlir::TypeConverter &typeConverter) const { cir::IntType ptrdiffCIRTy = getPtrDiffCIRTy(LM); - auto loweredMethodTy = mlir::cast( - lowerMethodType(attr.getType(), typeConverter)); + auto loweredMethodTy = mlir::cast(getMethodABIType()); auto zero = cir::IntAttr::get(ptrdiffCIRTy, 0); @@ -458,12 +450,12 @@ static mlir::Value lowerDataMemberCast(mlir::Operation *op, return loweredSrc; auto nullValue = builder.create( - op->getLoc(), mlir::IntegerAttr::get(loweredSrc.getType(), -1)); + op->getLoc(), cir::IntAttr::get(loweredSrc.getType(), -1)); auto isNull = builder.create(op->getLoc(), cir::CmpOpKind::eq, loweredSrc, nullValue); auto offsetValue = builder.create( - op->getLoc(), mlir::IntegerAttr::get(loweredSrc.getType(), offset)); + op->getLoc(), cir::IntAttr::get(loweredSrc.getType(), offset)); auto binOpKind = isDerivedToBase ? cir::BinOpKind::Sub : cir::BinOpKind::Add; auto adjustedPtr = builder.create( op->getLoc(), loweredSrc.getType(), binOpKind, loweredSrc, offsetValue); @@ -587,8 +579,7 @@ mlir::Value ItaniumCXXABI::lowerDataMemberBitcast(cir::CastOp op, mlir::Type loweredDstTy, mlir::Value loweredSrc, mlir::OpBuilder &builder) const { - return builder.create(op.getLoc(), loweredDstTy, - cir::CastKind::bitcast, loweredSrc); + return loweredSrc; } mlir::Value diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp index d040c87282f5..86a7bb394013 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp @@ -232,6 +232,12 @@ llvm::LogicalResult LowerModule::rewriteFunctionCall(CallOp callOp, // TODO: not to create it every time std::unique_ptr createLowerModule(mlir::ModuleOp module, mlir::PatternRewriter &rewriter) { + // If the triple is not present, e.g. CIR modules parsed from text, we + // cannot init LowerModule properly. + assert(!cir::MissingFeatures::makeTripleAlwaysPresent()); + if (!module->hasAttr(cir::CIRDialect::getTripleAttrName())) + return nullptr; + // Fetch target information. llvm::Triple triple(mlir::cast( module->getAttr(cir::CIRDialect::getTripleAttrName())) diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index b7e144c4b65f..08e1cfb99267 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -1128,42 +1128,6 @@ mlir::LogicalResult CIRToLLVMDerivedClassAddrOpLowering::matchAndRewrite( return mlir::success(); } -mlir::LogicalResult CIRToLLVMBaseDataMemberOpLowering::matchAndRewrite( - cir::BaseDataMemberOp op, OpAdaptor adaptor, - mlir::ConversionPatternRewriter &rewriter) const { - mlir::Value loweredResult = - lowerMod->getCXXABI().lowerBaseDataMember(op, adaptor.getSrc(), rewriter); - rewriter.replaceOp(op, loweredResult); - return mlir::success(); -} - -mlir::LogicalResult CIRToLLVMDerivedDataMemberOpLowering::matchAndRewrite( - cir::DerivedDataMemberOp op, OpAdaptor adaptor, - mlir::ConversionPatternRewriter &rewriter) const { - mlir::Value loweredResult = lowerMod->getCXXABI().lowerDerivedDataMember( - op, adaptor.getSrc(), rewriter); - rewriter.replaceOp(op, loweredResult); - return mlir::success(); -} - -mlir::LogicalResult CIRToLLVMBaseMethodOpLowering::matchAndRewrite( - cir::BaseMethodOp op, OpAdaptor adaptor, - mlir::ConversionPatternRewriter &rewriter) const { - mlir::Value loweredResult = - lowerMod->getCXXABI().lowerBaseMethod(op, adaptor.getSrc(), rewriter); - rewriter.replaceOp(op, loweredResult); - return mlir::success(); -} - -mlir::LogicalResult CIRToLLVMDerivedMethodOpLowering::matchAndRewrite( - cir::DerivedMethodOp op, OpAdaptor adaptor, - mlir::ConversionPatternRewriter &rewriter) const { - mlir::Value loweredResult = - lowerMod->getCXXABI().lowerDerivedMethod(op, adaptor.getSrc(), rewriter); - rewriter.replaceOp(op, loweredResult); - return mlir::success(); -} - static mlir::Value getValueForVTableSymbol(mlir::Operation *op, mlir::ConversionPatternRewriter &rewriter, @@ -1392,20 +1356,6 @@ mlir::LogicalResult CIRToLLVMCastOpLowering::matchAndRewrite( case cir::CastKind::bitcast: { auto dstTy = castOp.getType(); auto llvmDstTy = getTypeConverter()->convertType(dstTy); - - if (mlir::isa( - castOp.getSrc().getType())) { - mlir::Value loweredResult; - if (mlir::isa(castOp.getSrc().getType())) - loweredResult = lowerMod->getCXXABI().lowerDataMemberBitcast( - castOp, llvmDstTy, src, rewriter); - else - loweredResult = lowerMod->getCXXABI().lowerMethodBitcast( - castOp, llvmDstTy, src, rewriter); - rewriter.replaceOp(castOp, loweredResult); - return mlir::success(); - } - auto llvmSrcVal = adaptor.getSrc(); rewriter.replaceOpWithNewOp(castOp, llvmDstTy, llvmSrcVal); @@ -1428,17 +1378,6 @@ mlir::LogicalResult CIRToLLVMCastOpLowering::matchAndRewrite( llvmSrcVal); break; } - case cir::CastKind::member_ptr_to_bool: { - mlir::Value loweredResult; - if (mlir::isa(castOp.getSrc().getType())) - loweredResult = - lowerMod->getCXXABI().lowerMethodToBoolCast(castOp, src, rewriter); - else - loweredResult = lowerMod->getCXXABI().lowerDataMemberToBoolCast( - castOp, src, rewriter); - rewriter.replaceOp(castOp, loweredResult); - break; - } default: { return castOp.emitError("Unhandled cast kind: ") << castOp.getKindAttrName(); @@ -1942,22 +1881,6 @@ mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite( return mlir::success(); } attr = op.getValue(); - } else if (mlir::isa(op.getType())) { - assert(lowerMod && "lower module is not available"); - auto dataMember = mlir::cast(op.getValue()); - mlir::DataLayout layout(op->getParentOfType()); - mlir::TypedAttr abiValue = lowerMod->getCXXABI().lowerDataMemberConstant( - dataMember, layout, *typeConverter); - rewriter.replaceOpWithNewOp(op, abiValue); - return mlir::success(); - } else if (mlir::isa(op.getType())) { - assert(lowerMod && "lower module is not available"); - auto method = mlir::cast(op.getValue()); - mlir::DataLayout layout(op->getParentOfType()); - mlir::TypedAttr abiValue = lowerMod->getCXXABI().lowerMethodConstant( - method, layout, *typeConverter); - rewriter.replaceOpWithNewOp(op, abiValue); - return mlir::success(); } // TODO(cir): constant arrays are currently just pushed into the stack using // the store instruction, instead of being stored as global variables and @@ -2584,16 +2507,6 @@ mlir::LogicalResult CIRToLLVMGlobalOpLowering::lowerInitializer( } else if (mlir::isa(init)) { return lowerInitializerForConstComplex(rewriter, op, init, useInitializerRegion); - } else if (auto dataMemberAttr = mlir::dyn_cast(init)) { - assert(lowerMod && "lower module is not available"); - mlir::DataLayout layout(op->getParentOfType()); - mlir::TypedAttr abiValue = lowerMod->getCXXABI().lowerDataMemberConstant( - dataMemberAttr, layout, *typeConverter); - init = abiValue; - llvmType = convertTypeForMemory(*getTypeConverter(), dataLayout, - abiValue.getType()); - // Recursively lower the CIR attribute produced by CXXABI. - return lowerInitializer(rewriter, op, llvmType, init, useInitializerRegion); } else { op.emitError() << "unsupported initializer '" << init << "'"; return mlir::failure(); @@ -3179,21 +3092,6 @@ mlir::LogicalResult CIRToLLVMCmpOpLowering::matchAndRewrite( mlir::ConversionPatternRewriter &rewriter) const { auto type = cmpOp.getLhs().getType(); - if (mlir::isa(type)) { - assert(lowerMod && "lowering module is not available"); - - mlir::Value loweredResult; - if (mlir::isa(type)) - loweredResult = lowerMod->getCXXABI().lowerDataMemberCmp( - cmpOp, adaptor.getLhs(), adaptor.getRhs(), rewriter); - else - loweredResult = lowerMod->getCXXABI().lowerMethodCmp( - cmpOp, adaptor.getLhs(), adaptor.getRhs(), rewriter); - - rewriter.replaceOp(cmpOp, loweredResult); - return mlir::success(); - } - // Lower to LLVM comparison op. // if (auto intTy = mlir::dyn_cast(type)) { if (mlir::isa(type)) { @@ -3789,28 +3687,6 @@ mlir::LogicalResult CIRToLLVMInsertMemberOpLowering::matchAndRewrite( return mlir::success(); } -mlir::LogicalResult CIRToLLVMGetMethodOpLowering::matchAndRewrite( - cir::GetMethodOp op, OpAdaptor adaptor, - mlir::ConversionPatternRewriter &rewriter) const { - assert(lowerMod && "lowering module is not available"); - mlir::Value loweredResults[2]; - lowerMod->getCXXABI().lowerGetMethod(op, loweredResults, adaptor.getMethod(), - adaptor.getObject(), rewriter); - rewriter.replaceOp(op, loweredResults); - return mlir::success(); -} - -mlir::LogicalResult CIRToLLVMGetRuntimeMemberOpLowering::matchAndRewrite( - cir::GetRuntimeMemberOp op, OpAdaptor adaptor, - mlir::ConversionPatternRewriter &rewriter) const { - assert(lowerMod && "lowering module is not available"); - mlir::Type llvmResTy = getTypeConverter()->convertType(op.getType()); - mlir::Operation *llvmOp = lowerMod->getCXXABI().lowerGetRuntimeMember( - op, llvmResTy, adaptor.getAddr(), adaptor.getMember(), rewriter); - rewriter.replaceOp(op, llvmOp); - return mlir::success(); -} - uint64_t CIRToLLVMPtrDiffOpLowering::getTypeSize(mlir::Type type, mlir::Operation &op) const { mlir::DataLayout layout(op.getParentOfType()); @@ -4453,27 +4329,20 @@ void populateCIRToLLVMConversionPatterns( argsVarMap, patterns.getContext()); patterns.add< // clang-format off - CIRToLLVMCastOpLowering, CIRToLLVMLoadOpLowering, - CIRToLLVMStoreOpLowering, - CIRToLLVMGlobalOpLowering, - CIRToLLVMConstantOpLowering + CIRToLLVMStoreOpLowering // clang-format on >(converter, patterns.getContext(), lowerModule, dataLayout); patterns.add< // clang-format off - CIRToLLVMBaseDataMemberOpLowering, - CIRToLLVMBaseMethodOpLowering, - CIRToLLVMCmpOpLowering, - CIRToLLVMDerivedDataMemberOpLowering, - CIRToLLVMDerivedMethodOpLowering, - CIRToLLVMGetMethodOpLowering, - CIRToLLVMGetRuntimeMemberOpLowering, CIRToLLVMInvariantGroupOpLowering // clang-format on >(converter, patterns.getContext(), lowerModule); patterns.add< // clang-format off + CIRToLLVMCastOpLowering, + CIRToLLVMConstantOpLowering, + CIRToLLVMGlobalOpLowering, CIRToLLVMPtrStrideOpLowering, CIRToLLVMGetElementOpLowering, CIRToLLVMInlineAsmOpLowering @@ -4505,6 +4374,7 @@ void populateCIRToLLVMConversionPatterns( CIRToLLVMCallOpLowering, CIRToLLVMCatchParamOpLowering, CIRToLLVMClearCacheOpLowering, + CIRToLLVMCmpOpLowering, CIRToLLVMCmpThreeWayOpLowering, CIRToLLVMComplexCreateOpLowering, CIRToLLVMComplexImagOpLowering, @@ -4574,16 +4444,6 @@ void populateCIRToLLVMConversionPatterns( >(converter, patterns.getContext()); } -std::unique_ptr prepareLowerModule(mlir::ModuleOp module) { - mlir::PatternRewriter rewriter{module->getContext()}; - // If the triple is not present, e.g. CIR modules parsed from text, we - // cannot init LowerModule properly. - assert(!cir::MissingFeatures::makeTripleAlwaysPresent()); - if (!module->hasAttr(cir::CIRDialect::getTripleAttrName())) - return {}; - return cir::createLowerModule(module, rewriter); -} - static unsigned getTargetAddrSpaceFromCIRAddrSpace(cir::AddressSpace addrSpace, cir::LowerModule *lowerModule) { @@ -4613,19 +4473,6 @@ void prepareTypeConverter(mlir::LLVMTypeConverter &converter, assert(!cir::MissingFeatures::addressSpace()); return mlir::LLVM::LLVMPointerType::get(type.getContext()); }); - converter.addConversion( - [&, lowerModule](cir::DataMemberType type) -> mlir::Type { - assert(lowerModule && "CXXABI is not available"); - mlir::Type abiType = - lowerModule->getCXXABI().lowerDataMemberType(type, converter); - return converter.convertType(abiType); - }); - converter.addConversion([&, lowerModule](cir::MethodType type) -> mlir::Type { - assert(lowerModule && "CXXABI is not available"); - mlir::Type abiType = - lowerModule->getCXXABI().lowerMethodType(type, converter); - return converter.convertType(abiType); - }); converter.addConversion([&](cir::ArrayType type) -> mlir::Type { auto ty = convertTypeForMemory(converter, dataLayout, type.getElementType()); @@ -4952,7 +4799,9 @@ void ConvertCIRToLLVMPass::runOnOperation() { auto module = getOperation(); mlir::DataLayout dataLayout(module); mlir::LLVMTypeConverter converter(&getContext()); - std::unique_ptr lowerModule = prepareLowerModule(module); + mlir::PatternRewriter rewriter{module->getContext()}; + std::unique_ptr lowerModule = + cir::createLowerModule(module, rewriter); prepareTypeConverter(converter, dataLayout, lowerModule.get()); mlir::RewritePatternSet patterns(&getContext()); diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h index 01bc7c12be6e..305f6b19bbfb 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h @@ -52,8 +52,6 @@ void populateCIRToLLVMConversionPatterns( llvm::StringMap &argStringGlobalsMap, llvm::MapVector &argsVarMap); -std::unique_ptr prepareLowerModule(mlir::ModuleOp module); - void prepareTypeConverter(mlir::LLVMTypeConverter &converter, mlir::DataLayout &dataLayout, cir::LowerModule *lowerModule); @@ -194,66 +192,6 @@ class CIRToLLVMDerivedClassAddrOpLowering mlir::ConversionPatternRewriter &) const override; }; -class CIRToLLVMBaseDataMemberOpLowering - : public mlir::OpConversionPattern { - cir::LowerModule *lowerMod; - -public: - CIRToLLVMBaseDataMemberOpLowering(const mlir::TypeConverter &typeConverter, - mlir::MLIRContext *context, - cir::LowerModule *lowerModule) - : OpConversionPattern(typeConverter, context), lowerMod(lowerModule) {} - - mlir::LogicalResult - matchAndRewrite(cir::BaseDataMemberOp op, OpAdaptor, - mlir::ConversionPatternRewriter &) const override; -}; - -class CIRToLLVMDerivedDataMemberOpLowering - : public mlir::OpConversionPattern { - cir::LowerModule *lowerMod; - -public: - CIRToLLVMDerivedDataMemberOpLowering(const mlir::TypeConverter &typeConverter, - mlir::MLIRContext *context, - cir::LowerModule *lowerModule) - : OpConversionPattern(typeConverter, context), lowerMod(lowerModule) {} - - mlir::LogicalResult - matchAndRewrite(cir::DerivedDataMemberOp op, OpAdaptor, - mlir::ConversionPatternRewriter &) const override; -}; - -class CIRToLLVMBaseMethodOpLowering - : public mlir::OpConversionPattern { - cir::LowerModule *lowerMod; - -public: - CIRToLLVMBaseMethodOpLowering(const mlir::TypeConverter &typeConverter, - mlir::MLIRContext *context, - cir::LowerModule *lowerModule) - : OpConversionPattern(typeConverter, context), lowerMod(lowerModule) {} - - mlir::LogicalResult - matchAndRewrite(cir::BaseMethodOp op, OpAdaptor, - mlir::ConversionPatternRewriter &) const override; -}; - -class CIRToLLVMDerivedMethodOpLowering - : public mlir::OpConversionPattern { - cir::LowerModule *lowerMod; - -public: - CIRToLLVMDerivedMethodOpLowering(const mlir::TypeConverter &typeConverter, - mlir::MLIRContext *context, - cir::LowerModule *lowerModule) - : OpConversionPattern(typeConverter, context), lowerMod(lowerModule) {} - - mlir::LogicalResult - matchAndRewrite(cir::DerivedMethodOp op, OpAdaptor, - mlir::ConversionPatternRewriter &) const override; -}; - class CIRToLLVMVTTAddrPointOpLowering : public mlir::OpConversionPattern { public: @@ -275,7 +213,6 @@ class CIRToLLVMBrCondOpLowering }; class CIRToLLVMCastOpLowering : public mlir::OpConversionPattern { - cir::LowerModule *lowerMod; mlir::DataLayout const &dataLayout; mlir::Type convertTy(mlir::Type ty) const; @@ -283,10 +220,8 @@ class CIRToLLVMCastOpLowering : public mlir::OpConversionPattern { public: CIRToLLVMCastOpLowering(const mlir::TypeConverter &typeConverter, mlir::MLIRContext *context, - cir::LowerModule *lowerModule, mlir::DataLayout const &dataLayout) - : OpConversionPattern(typeConverter, context), lowerMod(lowerModule), - dataLayout(dataLayout) {} + : OpConversionPattern(typeConverter, context), dataLayout(dataLayout) {} mlir::LogicalResult matchAndRewrite(cir::CastOp op, OpAdaptor, @@ -404,16 +339,13 @@ class CIRToLLVMStoreOpLowering class CIRToLLVMConstantOpLowering : public mlir::OpConversionPattern { - cir::LowerModule *lowerMod; mlir::DataLayout const &dataLayout; public: CIRToLLVMConstantOpLowering(const mlir::TypeConverter &typeConverter, mlir::MLIRContext *context, - cir::LowerModule *lowerModule, mlir::DataLayout const &dataLayout) - : OpConversionPattern(typeConverter, context), lowerMod(lowerModule), - dataLayout(dataLayout) { + : OpConversionPattern(typeConverter, context), dataLayout(dataLayout) { setHasBoundedRewriteRecursion(); } @@ -618,16 +550,13 @@ class CIRToLLVMSwitchFlatOpLowering class CIRToLLVMGlobalOpLowering : public mlir::OpConversionPattern { - cir::LowerModule *lowerMod; mlir::DataLayout const &dataLayout; public: CIRToLLVMGlobalOpLowering(const mlir::TypeConverter &typeConverter, mlir::MLIRContext *context, - cir::LowerModule *lowerModule, mlir::DataLayout const &dataLayout) - : OpConversionPattern(typeConverter, context), lowerMod(lowerModule), - dataLayout(dataLayout) {} + : OpConversionPattern(typeConverter, context), dataLayout(dataLayout) {} mlir::LogicalResult matchAndRewrite(cir::GlobalOp op, OpAdaptor, @@ -724,15 +653,8 @@ class CIRToLLVMShiftOpLowering }; class CIRToLLVMCmpOpLowering : public mlir::OpConversionPattern { - cir::LowerModule *lowerMod; - public: - CIRToLLVMCmpOpLowering(const mlir::TypeConverter &typeConverter, - mlir::MLIRContext *context, - cir::LowerModule *lowerModule) - : OpConversionPattern(typeConverter, context), lowerMod(lowerModule) { - setHasBoundedRewriteRecursion(); - } + using mlir::OpConversionPattern::OpConversionPattern; mlir::LogicalResult matchAndRewrite(cir::CmpOp op, OpAdaptor, @@ -972,36 +894,6 @@ class CIRToLLVMInsertMemberOpLowering mlir::ConversionPatternRewriter &) const override; }; -class CIRToLLVMGetMethodOpLowering - : public mlir::OpConversionPattern { - cir::LowerModule *lowerMod; - -public: - CIRToLLVMGetMethodOpLowering(const mlir::TypeConverter &typeConverter, - mlir::MLIRContext *context, - cir::LowerModule *lowerModule) - : OpConversionPattern(typeConverter, context), lowerMod(lowerModule) {} - - mlir::LogicalResult - matchAndRewrite(cir::GetMethodOp op, OpAdaptor, - mlir::ConversionPatternRewriter &) const override; -}; - -class CIRToLLVMGetRuntimeMemberOpLowering - : public mlir::OpConversionPattern { - cir::LowerModule *lowerMod; - -public: - CIRToLLVMGetRuntimeMemberOpLowering(const mlir::TypeConverter &typeConverter, - mlir::MLIRContext *context, - cir::LowerModule *lowerModule) - : OpConversionPattern(typeConverter, context), lowerMod(lowerModule) {} - - mlir::LogicalResult - matchAndRewrite(cir::GetRuntimeMemberOp op, OpAdaptor, - mlir::ConversionPatternRewriter &) const override; -}; - class CIRToLLVMPtrDiffOpLowering : public mlir::OpConversionPattern { uint64_t getTypeSize(mlir::Type type, mlir::Operation &op) const; diff --git a/clang/test/CIR/Transforms/ABILowering/cast.cir b/clang/test/CIR/Transforms/ABILowering/cast.cir new file mode 100644 index 000000000000..f333ab552b87 --- /dev/null +++ b/clang/test/CIR/Transforms/ABILowering/cast.cir @@ -0,0 +1,53 @@ +// RUN: cir-opt --cir-abi-lowering -o %t.cir %s +// RUN: FileCheck --input-file %t.cir %s + +!s32i = !cir.int +!s64i = !cir.int +!S1 = !cir.record +!S2 = !cir.record +!Field1 = !cir.data_member +!Field2 = !cir.data_member +!Method1 = !cir.method in !S1> +!Method2 = !cir.method in !S2> + +module attributes { + cir.triple = "x86_64-unknown-linux-gnu", + dlti.dl_spec = #dlti.dl_spec : vector<2xi64>, f80 = dense<128> : vector<2xi64>, !llvm.ptr<271> = dense<32> : vector<4xi64>, !llvm.ptr<272> = dense<64> : vector<4xi64>, i64 = dense<64> : vector<2xi64>, f16 = dense<16> : vector<2xi64>, i32 = dense<32> : vector<2xi64>, f128 = dense<128> : vector<2xi64>, !llvm.ptr<270> = dense<32> : vector<4xi64>, f64 = dense<64> : vector<2xi64>, !llvm.ptr = dense<64> : vector<4xi64>, i1 = dense<8> : vector<2xi64>, i8 = dense<8> : vector<2xi64>, i16 = dense<16> : vector<2xi64>, "dlti.stack_alignment" = 128 : i64, "dlti.endianness" = "little"> +} { + cir.func @bitcast_data_member(%arg0 : !Field1) -> !Field2 { + %0 = cir.cast(bitcast, %arg0: !Field1), !Field2 + cir.return %0 : !Field2 + } + // CHECK: @bitcast_data_member(%[[ARG:.+]]: !s64i) -> !s64i + // CHECK-NEXT: cir.return %[[ARG]] : !s64i + // CHECK-NEXT: } + + cir.func @bitcast_method(%arg0 : !Method1) -> !Method2 { + %0 = cir.cast(bitcast, %arg0: !Method1), !Method2 + cir.return %0 : !Method2 + } + // CHECK: @bitcast_method(%[[ARG:.+]]: ![[ABI_TY:.+]]) -> ![[ABI_TY]] + // CHECK-NEXT: cir.return %[[ARG]] : ![[ABI_TY]] + // CHECK-NEXT: } + + cir.func @data_member_to_bool(%arg0 : !Field1) -> !cir.bool { + %0 = cir.cast(member_ptr_to_bool, %arg0 : !Field1), !cir.bool + cir.return %0 : !cir.bool + } + // CHECK: @data_member_to_bool(%[[ARG:.+]]: !s64i) -> !cir.bool + // CHECK-NEXT: %[[NULL:.+]] = cir.const #cir.int<-1> : !s64i + // CHECK-NEXT: %[[RES:.+]] = cir.cmp(ne, %[[ARG]], %[[NULL]]) : !s64i, !cir.bool + // CHECK-NEXT: cir.return %[[RES]] : !cir.bool + // CHECK-NEXT: } + + cir.func @method_to_bool(%arg0 : !Method1) -> !cir.bool { + %0 = cir.cast(member_ptr_to_bool, %arg0 : !Method1), !cir.bool + cir.return %0 : !cir.bool + } + // CHECK: @method_to_bool(%[[ARG:.+]]: ![[ABI_TY:.+]]) -> !cir.bool + // CHECK-NEXT: %[[NULL:.+]] = cir.const #cir.int<0> : !s64i + // CHECK-NEXT: %[[PTR:.+]] = cir.extract_member %[[ARG]][0] : ![[ABI_TY]] -> !s64i + // CHECK-NEXT: %[[RES:.+]] = cir.cmp(ne, %[[PTR]], %[[NULL]]) : !s64i, !cir.bool + // CHECK-NEXT: cir.return %[[RES]] : !cir.bool + // CHECK-NEXT: } +} diff --git a/clang/test/CIR/Transforms/ABILowering/cmp.cir b/clang/test/CIR/Transforms/ABILowering/cmp.cir new file mode 100644 index 000000000000..6aa999aada95 --- /dev/null +++ b/clang/test/CIR/Transforms/ABILowering/cmp.cir @@ -0,0 +1,41 @@ +// RUN: cir-opt --cir-abi-lowering -o %t.cir %s +// RUN: FileCheck --input-file %t.cir %s + +!s32i = !cir.int +!S = !cir.record +!Field = !cir.data_member +!Method = !cir.method in !S> + +module attributes { + cir.triple = "x86_64-unknown-linux-gnu", + dlti.dl_spec = #dlti.dl_spec : vector<2xi64>, f80 = dense<128> : vector<2xi64>, !llvm.ptr<271> = dense<32> : vector<4xi64>, !llvm.ptr<272> = dense<64> : vector<4xi64>, i64 = dense<64> : vector<2xi64>, f16 = dense<16> : vector<2xi64>, i32 = dense<32> : vector<2xi64>, f128 = dense<128> : vector<2xi64>, !llvm.ptr<270> = dense<32> : vector<4xi64>, f64 = dense<64> : vector<2xi64>, !llvm.ptr = dense<64> : vector<4xi64>, i1 = dense<8> : vector<2xi64>, i8 = dense<8> : vector<2xi64>, i16 = dense<16> : vector<2xi64>, "dlti.stack_alignment" = 128 : i64, "dlti.endianness" = "little"> +} { + cir.func @cmp_data_member(%arg0: !Field, %arg1: !Field) -> !cir.bool { + %0 = cir.cmp(eq, %arg0, %arg1) : !Field, !cir.bool + cir.return %0 : !cir.bool + } + // CHECK: @cmp_data_member(%[[ARG0:.+]]: !s64i, %[[ARG1:.+]]: !s64i) -> !cir.bool + // CHECK-NEXT: %[[RES:.+]] = cir.cmp(eq, %[[ARG0]], %[[ARG1]]) : !s64i, !cir.bool + // CHECK-NEXT: cir.return %[[RES]] : !cir.bool + // CHECK-NEXT: } + + cir.func @cmp_method(%arg0: !Method, %arg1: !Method) -> !cir.bool { + %0 = cir.cmp(eq, %arg0, %arg1) : !Method, !cir.bool + cir.return %0 : !cir.bool + } + // CHECK: @cmp_method(%[[ARG0:.+]]: ![[ABI_TY:.+]], %[[ARG1:.+]]: ![[ABI_TY]]) -> !cir.bool + // CHECK-NEXT: %[[ZERO:.+]] = cir.const #cir.int<0> : !s64i + // CHECK-NEXT: %[[ARG0_PTR:.+]] = cir.extract_member %[[ARG0]][0] : ![[ABI_TY]] -> !s64i + // CHECK-NEXT: %[[ARG1_PTR:.+]] = cir.extract_member %[[ARG1]][0] : ![[ABI_TY]] -> !s64i + // CHECK-NEXT: %[[PTR_EQ:.+]] = cir.cmp(eq, %[[ARG0_PTR]], %[[ARG1_PTR]]) : !s64i, !cir.bool + // CHECK-NEXT: %[[ARG0_PTR_NULL:.+]] = cir.cmp(eq, %[[ARG0_PTR]], %[[ZERO]]) : !s64i, !cir.bool + // CHECK-NEXT: %[[ARG0_OFFSET:.+]] = cir.extract_member %[[ARG0]][1] : ![[ABI_TY]] -> !s64i + // CHECK-NEXT: %[[ARG1_OFFSET:.+]] = cir.extract_member %[[ARG1]][1] : ![[ABI_TY]] -> !s64i + // CHECK-NEXT: %[[OFFSET_EQ:.+]] = cir.cmp(eq, %[[ARG0_OFFSET]], %[[ARG1_OFFSET]]) : !s64i, !cir.bool + // CHECK-NEXT: %[[TRUE:.+]] = cir.const #true + // CHECK-NEXT: %[[FALSE:.+]] = cir.const #false + // CHECK-NEXT: %[[X:.+]] = cir.select if %[[ARG0_PTR_NULL]] then %[[TRUE]] else %[[OFFSET_EQ]] : (!cir.bool, !cir.bool, !cir.bool) -> !cir.bool + // CHECK-NEXT: %[[RES:.+]] = cir.select if %[[X]] then %[[PTR_EQ]] else %[[FALSE]] : (!cir.bool, !cir.bool, !cir.bool) -> !cir.bool + // CHECK-NEXT: cir.return %[[RES]] : !cir.bool + // CHECK-NEXT: } +} diff --git a/clang/test/CIR/Transforms/ABILowering/const.cir b/clang/test/CIR/Transforms/ABILowering/const.cir new file mode 100644 index 000000000000..62fc40682c93 --- /dev/null +++ b/clang/test/CIR/Transforms/ABILowering/const.cir @@ -0,0 +1,40 @@ +// RUN: cir-opt --cir-abi-lowering -o %t.cir %s +// RUN: FileCheck --input-file %t.cir %s + +!s32i = !cir.int +!S = !cir.record +!Field = !cir.data_member +!Method = !cir.method in !S> + +module attributes { + cir.triple = "x86_64-unknown-linux-gnu", + dlti.dl_spec = #dlti.dl_spec : vector<2xi64>, f80 = dense<128> : vector<2xi64>, !llvm.ptr<271> = dense<32> : vector<4xi64>, !llvm.ptr<272> = dense<64> : vector<4xi64>, i64 = dense<64> : vector<2xi64>, f16 = dense<16> : vector<2xi64>, i32 = dense<32> : vector<2xi64>, f128 = dense<128> : vector<2xi64>, !llvm.ptr<270> = dense<32> : vector<4xi64>, f64 = dense<64> : vector<2xi64>, !llvm.ptr = dense<64> : vector<4xi64>, i1 = dense<8> : vector<2xi64>, i8 = dense<8> : vector<2xi64>, i16 = dense<16> : vector<2xi64>, "dlti.stack_alignment" = 128 : i64, "dlti.endianness" = "little"> +} { + cir.func @const_data_member() -> !Field { + %0 = cir.const #cir.data_member<1> : !Field + cir.return %0 : !Field + } + // CHECK: @const_data_member() -> !s64i + // CHECK-NEXT: %[[RES:.+]] = cir.const #cir.int<4> : !s64i + // CHECK-NEXT: cir.return %[[RES]] : !s64i + // CHECK-NEXT: } + + cir.func private @f(%arg0: !cir.ptr, %arg1: !s32i) + cir.func @const_method_nonvirtual() -> !Method { + %0 = cir.const #cir.method<@f> : !Method + cir.return %0 : !Method + } + // CHECK: @const_method_nonvirtual() -> ![[ABI_TY:.+]] { + // CHECK-NEXT: %[[RES:.+]] = cir.const #cir.const_record<{#cir.global_view<@f> : !s64i, #cir.int<0> : !s64i}> : ![[ABI_TY]] + // CHECK-NEXT: cir.return %[[RES]] : ![[ABI_TY]] + // CHECK-NEXT: } + + cir.func @const_method_virtual() -> !Method { + %0 = cir.const #cir.method : !Method + cir.return %0 : !Method + } + // CHECK: cir.func @const_method_virtual() -> ![[ABI_TY:.+]] { + // CHECK-NEXT: %[[RES:.+]] = cir.const #cir.const_record<{#cir.int<9> : !s64i, #cir.int<0> : !s64i}> : ![[ABI_TY]] + // CHECK-NEXT: cir.return %[[RES]] : ![[ABI_TY]] + // CHECK-NEXT: } +} diff --git a/clang/test/CIR/Transforms/ABILowering/func.cir b/clang/test/CIR/Transforms/ABILowering/func.cir new file mode 100644 index 000000000000..c8482024ceab --- /dev/null +++ b/clang/test/CIR/Transforms/ABILowering/func.cir @@ -0,0 +1,28 @@ +// RUN: cir-opt --cir-abi-lowering -o %t.cir %s +// RUN: FileCheck --input-file %t.cir %s + +!s32i = !cir.int +!S = !cir.record +!Field = !cir.data_member +!Method = !cir.method in !S> + +module attributes { + cir.triple = "x86_64-unknown-linux-gnu", + dlti.dl_spec = #dlti.dl_spec : vector<2xi64>, f80 = dense<128> : vector<2xi64>, !llvm.ptr<271> = dense<32> : vector<4xi64>, !llvm.ptr<272> = dense<64> : vector<4xi64>, i64 = dense<64> : vector<2xi64>, f16 = dense<16> : vector<2xi64>, i32 = dense<32> : vector<2xi64>, f128 = dense<128> : vector<2xi64>, !llvm.ptr<270> = dense<32> : vector<4xi64>, f64 = dense<64> : vector<2xi64>, !llvm.ptr = dense<64> : vector<4xi64>, i1 = dense<8> : vector<2xi64>, i8 = dense<8> : vector<2xi64>, i16 = dense<16> : vector<2xi64>, "dlti.stack_alignment" = 128 : i64, "dlti.endianness" = "little"> +} { + cir.func @foo(%arg0 : !Field, %arg1: !Method) -> !Field { + cir.return %arg0 : !Field + } + // CHECK: @foo(%[[ARG0:.+]]: !s64i, %[[ARG1:.+]]: ![[METHOD_ABI_TY:.+]]) -> !s64i + // CHECK-NEXT: cir.return %[[ARG0]] : !s64i + // CHECK-NEXT: } + + cir.func @no_args() -> !Field { + %0 = cir.const #cir.data_member<1> : !Field + cir.return %0 : !Field + } + // CHECK: @no_args() -> !s64i + // CHECK-NEXT: %[[RES:.+]] = cir.const #cir.int<4> : !s64i + // CHECK-NEXT: cir.return %[[RES]] : !s64i + // CHECK-NEXT: } +} diff --git a/clang/test/CIR/Transforms/ABILowering/global.cir b/clang/test/CIR/Transforms/ABILowering/global.cir new file mode 100644 index 000000000000..6cf56057eb7c --- /dev/null +++ b/clang/test/CIR/Transforms/ABILowering/global.cir @@ -0,0 +1,22 @@ +// RUN: cir-opt --cir-abi-lowering -o %t.cir %s +// RUN: FileCheck --input-file %t.cir %s + +!s32i = !cir.int +!S = !cir.record +!Field = !cir.data_member +!Method = !cir.method in !S> + +module attributes { + cir.triple = "x86_64-unknown-linux-gnu", + dlti.dl_spec = #dlti.dl_spec : vector<2xi64>, f80 = dense<128> : vector<2xi64>, !llvm.ptr<271> = dense<32> : vector<4xi64>, !llvm.ptr<272> = dense<64> : vector<4xi64>, i64 = dense<64> : vector<2xi64>, f16 = dense<16> : vector<2xi64>, i32 = dense<32> : vector<2xi64>, f128 = dense<128> : vector<2xi64>, !llvm.ptr<270> = dense<32> : vector<4xi64>, f64 = dense<64> : vector<2xi64>, !llvm.ptr = dense<64> : vector<4xi64>, i1 = dense<8> : vector<2xi64>, i8 = dense<8> : vector<2xi64>, i16 = dense<16> : vector<2xi64>, "dlti.stack_alignment" = 128 : i64, "dlti.endianness" = "little"> +} { + cir.global external @const_data_member = #cir.data_member<1> : !Field + // CHECK: cir.global external @const_data_member = #cir.int<4> : !s64i + + cir.func private @f(%arg0: !cir.ptr, %arg1: !s32i) + cir.global external @const_method_nonvirtual = #cir.method<@f> : !Method + // CHECK: cir.global external @const_method_nonvirtual = #cir.const_record<{#cir.global_view<@f> : !s64i, #cir.int<0> : !s64i}> : !{{.+}} + + cir.global external @const_method_virtual = #cir.method : !Method + // CHECK: cir.global external @const_method_virtual = #cir.const_record<{#cir.int<9> : !s64i, #cir.int<0> : !s64i}> : !{{.+}} +} diff --git a/clang/test/CIR/Transforms/ABILowering/member-ptr.cir b/clang/test/CIR/Transforms/ABILowering/member-ptr.cir new file mode 100644 index 000000000000..3f1295258ee2 --- /dev/null +++ b/clang/test/CIR/Transforms/ABILowering/member-ptr.cir @@ -0,0 +1,106 @@ +// RUN: cir-opt --cir-abi-lowering -o %t.cir %s +// RUN: FileCheck --input-file %t.cir %s + +!void = !cir.void +!s32i = !cir.int +!s64i = !cir.int +!Base = !cir.record +!Derived = !cir.record +!BaseField = !cir.data_member +!DerivedField = !cir.data_member +!BaseMethod = !cir.method in !Base> +!DerivedMethod = !cir.method in !Derived> + +module attributes { + cir.triple = "x86_64-unknown-linux-gnu", + dlti.dl_spec = #dlti.dl_spec : vector<2xi64>, f80 = dense<128> : vector<2xi64>, !llvm.ptr<271> = dense<32> : vector<4xi64>, !llvm.ptr<272> = dense<64> : vector<4xi64>, i64 = dense<64> : vector<2xi64>, f16 = dense<16> : vector<2xi64>, i32 = dense<32> : vector<2xi64>, f128 = dense<128> : vector<2xi64>, !llvm.ptr<270> = dense<32> : vector<4xi64>, f64 = dense<64> : vector<2xi64>, !llvm.ptr = dense<64> : vector<4xi64>, i1 = dense<8> : vector<2xi64>, i8 = dense<8> : vector<2xi64>, i16 = dense<16> : vector<2xi64>, "dlti.stack_alignment" = 128 : i64, "dlti.endianness" = "little"> +} { + cir.func @get_runtime_member(%arg0: !cir.ptr, %arg1: !BaseField) -> !cir.ptr { + %0 = cir.get_runtime_member %arg0[%arg1 : !BaseField] : !cir.ptr -> !cir.ptr + cir.return %0 : !cir.ptr + } + // CHECK: cir.func @get_runtime_member(%[[ARG0:.+]]: !cir.ptr, %[[ARG1:.+]]: !s64i) -> !cir.ptr { + // CHECK-NEXT: %[[BYTE_PTR:.+]] = cir.cast(bitcast, %[[ARG0]] : !cir.ptr), !cir.ptr + // CHECK-NEXT: %[[COMPUTED:.+]] = cir.ptr_stride(%[[BYTE_PTR]] : !cir.ptr, %[[ARG1]] : !s64i), !cir.ptr + // CHECK-NEXT: %[[RESULT:.+]] = cir.cast(bitcast, %[[COMPUTED]] : !cir.ptr), !cir.ptr + // CHECK-NEXT: cir.return %[[RESULT]] : !cir.ptr + // CHECK-NEXT: } + + cir.func @get_method(%arg0: !cir.ptr, %arg1: !BaseMethod) { + %0, %1 = cir.get_method %arg1, %arg0 : (!BaseMethod, !cir.ptr) -> (!cir.ptr, !s32i)>>, !cir.ptr) + cir.return + } + // CHECK: cir.func @get_method(%[[ARG0:.+]]: !cir.ptr, %[[ARG1:.+]]: ![[ABI_TY:.+]]) { + // CHECK-NEXT: %[[MASK:.+]] = cir.const #cir.int<1> : !s64i + // CHECK-NEXT: %[[OFFSET:.+]] = cir.extract_member %[[ARG1]][1] : ![[ABI_TY]] -> !s64i + // CHECK-NEXT: %[[THIS:.+]] = cir.cast(bitcast, %[[ARG0]] : !cir.ptr), !cir.ptr + // CHECK-NEXT: %{{.+}} = cir.ptr_stride(%[[THIS]] : !cir.ptr, %[[OFFSET]] : !s64i), !cir.ptr + // CHECK-NEXT: %[[PTR:.+]] = cir.extract_member %[[ARG1]][0] : ![[ABI_TY]] -> !s64i + // CHECK-NEXT: %[[PTR_MASKED:.+]] = cir.binop(and, %[[PTR]], %[[MASK]]) : !s64i + // CHECK-NEXT: %[[IS_VIRT:.+]] = cir.cmp(eq, %[[PTR_MASKED]], %[[MASK]]) : !s64i, !cir.bool + // CHECK-NEXT: cir.brcond %[[IS_VIRT]] ^[[BLK_VIRT:.+]], ^[[BLK_NON_VIRT:.+]] + // CHECK-NEXT: ^[[BLK_VIRT]]: + // CHECK-NEXT: %[[VPTR_PTR:.+]] = cir.cast(bitcast, %[[ARG0]] : !cir.ptr), !cir.ptr> + // CHECK-NEXT: %[[VPTR:.+]] = cir.load %[[VPTR_PTR]] : !cir.ptr>, !cir.ptr + // CHECK-NEXT: %[[VPTR_OFFSET:.+]] = cir.binop(sub, %[[PTR]], %[[MASK]]) : !s64i + // CHECK-NEXT: %[[VELEM_PTR:.+]] = cir.ptr_stride(%[[VPTR]] : !cir.ptr, %[[VPTR_OFFSET]] : !s64i), !cir.ptr + // CHECK-NEXT: %[[VFPTR_PTR:.+]] = cir.cast(bitcast, %[[VELEM_PTR]] : !cir.ptr), !cir.ptr, !s32i)>>> + // CHECK-NEXT: %[[VFPTR:.+]] = cir.load %[[VFPTR_PTR]] : !cir.ptr, !s32i)>>>, !cir.ptr, !s32i)>> + // CHECK-NEXT: cir.br ^[[BLK_CONT:.+]](%[[VFPTR]] : !cir.ptr, !s32i)>>) + // CHECK-NEXT: ^[[BLK_NON_VIRT]]: + // CHECK-NEXT: %[[FPTR:.+]] = cir.cast(int_to_ptr, %[[PTR]] : !s64i), !cir.ptr, !s32i)>> + // CHECK-NEXT: cir.br ^[[BLK_CONT]](%[[FPTR]] : !cir.ptr, !s32i)>>) + // CHECK-NEXT: ^[[BLK_CONT]](%14: !cir.ptr, !s32i)>>): + // CHECK-NEXT: cir.return + // CHECK-NEXT: } + + cir.func @data_member_derived_to_base(%arg0: !DerivedField) -> !BaseField { + %0 = cir.base_data_member %arg0 : !DerivedField [8] -> !BaseField + cir.return %0 : !BaseField + } + // CHECK: @data_member_derived_to_base(%[[ARG:.+]]: !s64i) -> !s64i { + // CHECK-NEXT: %[[NULL:.+]] = cir.const #cir.int<-1> : !s64i + // CHECK-NEXT: %[[IS_NULL:.+]] = cir.cmp(eq, %[[ARG]], %[[NULL]]) : !s64i, !cir.bool + // CHECK-NEXT: %[[OFFSET:.+]] = cir.const #cir.int<8> : !s64i + // CHECK-NEXT: %[[COMPUTED:.+]] = cir.binop(sub, %[[ARG]], %[[OFFSET]]) : !s64i + // CHECK-NEXT: %[[RES:.+]] = cir.select if %[[IS_NULL]] then %[[NULL]] else %[[COMPUTED]] : (!cir.bool, !s64i, !s64i) -> !s64i + // CHECK-NEXT: cir.return %[[RES]] : !s64i + // CHECK-NEXT: } + + cir.func @data_member_base_to_derived(%arg0: !BaseField) -> !DerivedField { + %0 = cir.derived_data_member %arg0 : !BaseField [8] -> !DerivedField + cir.return %0 : !DerivedField + } + // CHECK: @data_member_base_to_derived(%[[ARG:.+]]: !s64i) -> !s64i { + // CHECK-NEXT: %[[NULL:.+]] = cir.const #cir.int<-1> : !s64i + // CHECK-NEXT: %[[IS_NULL:.+]] = cir.cmp(eq, %[[ARG]], %[[NULL]]) : !s64i, !cir.bool + // CHECK-NEXT: %[[OFFSET:.+]] = cir.const #cir.int<8> : !s64i + // CHECK-NEXT: %[[COMPUTED:.+]] = cir.binop(add, %[[ARG]], %[[OFFSET]]) : !s64i + // CHECK-NEXT: %[[RES:.+]] = cir.select if %[[IS_NULL]] then %[[NULL]] else %[[COMPUTED]] : (!cir.bool, !s64i, !s64i) -> !s64i + // CHECK-NEXT: cir.return %[[RES]] : !s64i + // CHECK-NEXT: } + + cir.func @method_derived_to_base(%arg0: !DerivedMethod) -> !BaseMethod { + %0 = cir.base_method %arg0 : !DerivedMethod [8] -> !BaseMethod + cir.return %0 : !BaseMethod + } + // CHECK: @method_derived_to_base(%[[ARG:.+]]: ![[ABI_TY:.+]]) -> ![[ABI_TY]] { + // CHECK-NEXT: %[[THIS_OFFSET:.+]] = cir.extract_member %[[ARG]][1] : ![[ABI_TY]] -> !s64i + // CHECK-NEXT: %[[BASE_OFFSET:.+]] = cir.const #cir.int<8> : !s64i + // CHECK-NEXT: %[[COMPUTED:.+]] = cir.binop(sub, %[[THIS_OFFSET]], %[[BASE_OFFSET]]) : !s64i + // CHECK-NEXT: %[[RES:.+]] = cir.insert_member %[[ARG]][1], %[[COMPUTED]] : ![[ABI_TY]], !s64i + // CHECK-NEXT: cir.return %[[RES]] : ![[ABI_TY]] + // CHECK-NEXT: } + + cir.func @method_base_to_derived(%arg0: !BaseMethod) -> !DerivedMethod { + %0 = cir.derived_method %arg0 : !BaseMethod [8] -> !DerivedMethod + cir.return %0 : !DerivedMethod + } + // CHECK: @method_base_to_derived(%[[ARG:.+]]: ![[ABI_TY:.+]]) -> ![[ABI_TY]] { + // CHECK-NEXT: %[[THIS_OFFSET:.+]] = cir.extract_member %[[ARG]][1] : ![[ABI_TY]] -> !s64i + // CHECK-NEXT: %[[BASE_OFFSET:.+]] = cir.const #cir.int<8> : !s64i + // CHECK-NEXT: %[[COMPUTED:.+]] = cir.binop(add, %[[THIS_OFFSET]], %[[BASE_OFFSET]]) : !s64i + // CHECK-NEXT: %[[RES:.+]] = cir.insert_member %[[ARG]][1], %[[COMPUTED]] : ![[ABI_TY]], !s64i + // CHECK-NEXT: cir.return %[[RES]] : ![[ABI_TY]] + // CHECK-NEXT: } +} \ No newline at end of file diff --git a/clang/tools/cir-opt/cir-opt.cpp b/clang/tools/cir-opt/cir-opt.cpp index 2c242f9d2db1..f3c41510ad4a 100644 --- a/clang/tools/cir-opt/cir-opt.cpp +++ b/clang/tools/cir-opt/cir-opt.cpp @@ -77,6 +77,10 @@ int main(int argc, char **argv) { return mlir::createReconcileUnrealizedCastsPass(); }); + ::mlir::registerPass([]() -> std::unique_ptr<::mlir::Pass> { + return mlir::createABILoweringPass(); + }); + mlir::registerTransformsPasses(); return failed(MlirOptMain(