[clang] [CIR] LLVMIR lowering for cir.call (PR #138873)
via cfe-commits
cfe-commits at lists.llvm.org
Wed May 7 06:48:05 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Sirui Mu (Lancern)
<details>
<summary>Changes</summary>
This PR adds LLVMIR lowering support for the `cir.call` operation.
---
Full diff: https://github.com/llvm/llvm-project/pull/138873.diff
4 Files Affected:
- (modified) clang/include/clang/CIR/MissingFeatures.h (+2)
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+45)
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h (+9)
- (modified) clang/test/CIR/CodeGen/call.cpp (+24-12)
``````````diff
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index eb75a073d1817..d49098768ad09 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -104,6 +104,8 @@ struct MissingFeatures {
static bool opCallExtParameterInfo() { return false; }
static bool opCallCIRGenFuncInfoParamInfo() { return false; }
static bool opCallCIRGenFuncInfoExtParamInfo() { return false; }
+ static bool opCallLandingPad() { return false; }
+ static bool opCallContinueBlock() { return false; }
// ScopeOp handling
static bool opScopeCleanupRegion() { return false; }
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 6137adb1e9936..8ba079a55f1c5 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -651,6 +651,50 @@ mlir::LogicalResult CIRToLLVMReturnOpLowering::matchAndRewrite(
return mlir::LogicalResult::success();
}
+static mlir::LogicalResult
+rewriteCallOrInvoke(mlir::Operation *op, mlir::ValueRange callOperands,
+ mlir::ConversionPatternRewriter &rewriter,
+ const mlir::TypeConverter *converter,
+ mlir::FlatSymbolRefAttr calleeAttr) {
+ llvm::SmallVector<mlir::Type, 8> llvmResults;
+ auto cirResults = op->getResultTypes();
+
+ if (converter->convertTypes(cirResults, llvmResults).failed())
+ return mlir::failure();
+
+ assert(!cir::MissingFeatures::opCallCallConv());
+ assert(!cir::MissingFeatures::opCallSideEffect());
+
+ mlir::LLVM::LLVMFunctionType llvmFnTy;
+ if (calleeAttr) { // direct call
+ auto fn =
+ mlir::SymbolTable::lookupNearestSymbolFrom<mlir::FunctionOpInterface>(
+ op, calleeAttr);
+ assert(fn && "Did not find function for call");
+ llvmFnTy = cast<mlir::LLVM::LLVMFunctionType>(
+ converter->convertType(fn.getFunctionType()));
+ } else { // indirect call
+ assert(!cir::MissingFeatures::opCallIndirect());
+ return op->emitError("Indirect calls are NYI");
+ }
+
+ assert(!cir::MissingFeatures::opCallLandingPad());
+ assert(!cir::MissingFeatures::opCallContinueBlock());
+ assert(!cir::MissingFeatures::opCallCallConv());
+ assert(!cir::MissingFeatures::opCallSideEffect());
+
+ rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(op, llvmFnTy, calleeAttr,
+ callOperands);
+ return mlir::success();
+}
+
+mlir::LogicalResult CIRToLLVMCallOpLowering::matchAndRewrite(
+ cir::CallOp op, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const {
+ return rewriteCallOrInvoke(op.getOperation(), adaptor.getOperands(), rewriter,
+ getTypeConverter(), op.getCalleeAttr());
+}
+
mlir::LogicalResult CIRToLLVMLoadOpLowering::matchAndRewrite(
cir::LoadOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const {
@@ -1589,6 +1633,7 @@ void ConvertCIRToLLVMPass::runOnOperation() {
CIRToLLVMBinOpLowering,
CIRToLLVMBrCondOpLowering,
CIRToLLVMBrOpLowering,
+ CIRToLLVMCallOpLowering,
CIRToLLVMCmpOpLowering,
CIRToLLVMConstantOpLowering,
CIRToLLVMFuncOpLowering,
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
index f248ea31e7844..0da4f9ba2c791 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
@@ -64,6 +64,15 @@ class CIRToLLVMReturnOpLowering
mlir::ConversionPatternRewriter &) const override;
};
+class CIRToLLVMCallOpLowering : public mlir::OpConversionPattern<cir::CallOp> {
+public:
+ using mlir::OpConversionPattern<cir::CallOp>::OpConversionPattern;
+
+ mlir::LogicalResult
+ matchAndRewrite(cir::CallOp op, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const override;
+};
+
class CIRToLLVMAllocaOpLowering
: public mlir::OpConversionPattern<cir::AllocaOp> {
mlir::DataLayout const &dataLayout;
diff --git a/clang/test/CIR/CodeGen/call.cpp b/clang/test/CIR/CodeGen/call.cpp
index f6dc5e15933ed..3b1ab8b5fc498 100644
--- a/clang/test/CIR/CodeGen/call.cpp
+++ b/clang/test/CIR/CodeGen/call.cpp
@@ -1,13 +1,19 @@
-// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o - 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
void f1() {}
void f2() {
f1();
}
-// CHECK-LABEL: cir.func @_Z2f1v
-// CHECK-LABEL: cir.func @_Z2f2v
-// CHECK: cir.call @_Z2f1v() : () -> ()
+// CIR-LABEL: cir.func @_Z2f1v
+// CIR-LABEL: cir.func @_Z2f2v
+// CIR: cir.call @_Z2f1v() : () -> ()
+
+// LLVM-LABEL: define void @_Z2f2v() {
+// LLVM: call void @_Z2f1v()
int f3() { return 2; }
int f4() {
@@ -15,9 +21,12 @@ int f4() {
return x;
}
-// CHECK-LABEL: cir.func @_Z2f3v() -> !s32i
-// CHECK-LABEL: cir.func @_Z2f4v() -> !s32i
-// CHECK: cir.call @_Z2f3v() : () -> !s32i
+// CIR-LABEL: cir.func @_Z2f3v() -> !s32i
+// CIR-LABEL: cir.func @_Z2f4v() -> !s32i
+// CIR: cir.call @_Z2f3v() : () -> !s32i
+
+// LLVM-LABEL: define i32 @_Z2f4v() {
+// LLVM: %{{.+}} = call i32 @_Z2f3v()
int f5(int a, int *b, bool c);
int f6() {
@@ -25,8 +34,11 @@ int f6() {
return f5(2, &b, false);
}
-// CHECK-LABEL: cir.func @_Z2f6v() -> !s32i
-// CHECK: %[[#b:]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["b", init]
-// CHECK: %[[#a:]] = cir.const #cir.int<2> : !s32i
-// CHECK-NEXT: %[[#c:]] = cir.const #false
-// CHECK-NEXT: %{{.+}} = cir.call @_Z2f5iPib(%[[#a]], %[[#b:]], %[[#c]]) : (!s32i, !cir.ptr<!s32i>, !cir.bool) -> !s32i
+// CIR-LABEL: cir.func @_Z2f6v() -> !s32i
+// CIR: %[[#b:]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["b", init]
+// CIR: %[[#a:]] = cir.const #cir.int<2> : !s32i
+// CIR-NEXT: %[[#c:]] = cir.const #false
+// CIR-NEXT: %{{.+}} = cir.call @_Z2f5iPib(%[[#a]], %[[#b:]], %[[#c]]) : (!s32i, !cir.ptr<!s32i>, !cir.bool) -> !s32i
+
+// LLVM-LABEL: define i32 @_Z2f6v() {
+// LLVM: %{{.+}} = call i32 @_Z2f5iPib(i32 2, ptr %{{.+}}, i1 false)
``````````
</details>
https://github.com/llvm/llvm-project/pull/138873
More information about the cfe-commits
mailing list