================
@@ -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

Reply via email to