From 9c59174024dc1a82451ae40386d2ac7e3eda789a Mon Sep 17 00:00:00 2001 From: gitoleg Date: Thu, 31 Oct 2024 13:19:54 +0300 Subject: [PATCH 1/3] [CIR][ABI][Lowering] call to fptr --- .../Dialect/Transforms/CallConvLowering.cpp | 2 +- .../TargetLowering/LowerFunction.cpp | 22 ++++++++++++-- .../Transforms/TargetLowering/LowerModule.h | 2 +- .../test/CIR/CallConvLowering/x86_64/fptrs.c | 29 +++++++++++++++++++ 4 files changed, 50 insertions(+), 5 deletions(-) diff --git a/clang/lib/CIR/Dialect/Transforms/CallConvLowering.cpp b/clang/lib/CIR/Dialect/Transforms/CallConvLowering.cpp index 9cdd734ef2a5..f29c67210288 100644 --- a/clang/lib/CIR/Dialect/Transforms/CallConvLowering.cpp +++ b/clang/lib/CIR/Dialect/Transforms/CallConvLowering.cpp @@ -103,7 +103,7 @@ struct CallConvLowering { rewriter.setInsertionPoint(op); auto typ = op.getIndirectCall().getType(); if (isFuncPointerTy(typ)) { - cir_cconv_unreachable("Indirect calls NYI"); + lowerModule->rewriteFunctionCall(op); } } diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp index fee7a752d7fb..7676815cf847 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp @@ -584,8 +584,16 @@ LogicalResult LowerFunction::rewriteCallOp(CallOp op, // NOTE(cir): There is no direct way to fetch the function type from the // CallOp, so we fetch it from the source function. This assumes the // function definition has not yet been lowered. - cir_cconv_assert(SrcFn && "No source function"); - auto fnType = SrcFn.getFunctionType(); + + FuncType fnType; + if (SrcFn) { + fnType = SrcFn.getFunctionType(); + } else if (op.isIndirect()) { + if (auto ptrTy = dyn_cast(op.getIndirectCall().getType())) + fnType = dyn_cast(ptrTy.getPointee()); + } + + cir_cconv_assert(fnType && "No callee function type"); // Rewrite the call operation to abide to the ABI calling convention. auto Ret = rewriteCallOp(fnType, SrcFn, op, retValSlot); @@ -641,7 +649,7 @@ Value LowerFunction::rewriteCallOp(FuncType calleeTy, FuncOp origCallee, // // Chain calls use this same code path to add the invisible chain parameter // to the function type. - if (origCallee.getNoProto() || Chain) { + if ((origCallee && origCallee.getNoProto()) || Chain) { cir_cconv_assert_or_abort(::cir::MissingFeatures::ABINoProtoFunctions(), "NYI"); } @@ -824,6 +832,14 @@ Value LowerFunction::rewriteCallOp(const LowerFunctionInfo &CallInfo, // NOTE(cir): We don't know if the callee was already lowered, so we only // fetch the name from the callee, while the return type is fetch from the // lowering types manager. + if (Caller.isIndirect()) { + rewriter.setInsertionPoint(Caller); + auto val = Caller.getIndirectCall(); + auto ptrTy = PointerType::get(val.getContext(), IRFuncTy); + auto callee = rewriter.create(val.getLoc(), ptrTy, CastKind::bitcast, val); + IRCallArgs.insert(IRCallArgs.begin(), callee); + } + CallOp newCallOp = rewriter.create( loc, Caller.getCalleeAttr(), IRFuncTy.getReturnType(), IRCallArgs); auto extraAttrs = diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h index 2d5e928e93f3..01a3dc273c94 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h @@ -96,7 +96,7 @@ class LowerModule { LogicalResult rewriteFunctionDefinition(FuncOp op); // Rewrite CIR CallOp to match the target ABI. - LogicalResult rewriteFunctionCall(CallOp callOp, FuncOp funcOp); + LogicalResult rewriteFunctionCall(CallOp callOp, FuncOp funcOp={}); }; std::unique_ptr createLowerModule(ModuleOp module, diff --git a/clang/test/CIR/CallConvLowering/x86_64/fptrs.c b/clang/test/CIR/CallConvLowering/x86_64/fptrs.c index 47111165d049..f2a7538919c2 100644 --- a/clang/test/CIR/CallConvLowering/x86_64/fptrs.c +++ b/clang/test/CIR/CallConvLowering/x86_64/fptrs.c @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir-flat -fclangir-call-conv-lowering %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm -fclangir-call-conv-lowering %s -o -| FileCheck %s -check-prefix=LLVM typedef struct { int a; @@ -16,3 +17,31 @@ int foo(S s) { return 42 + s.a; } void bar() { myfptr a = foo; } + +// CHECK: cir.func {{.*@baz}}(%arg0: !s32i +// CHECK: %[[#V0:]] = cir.alloca !ty_S, !cir.ptr, [""] {alignment = 4 : i64} +// CHECK: %[[#V1:]] = cir.cast(bitcast, %[[#V0]] : !cir.ptr), !cir.ptr +// CHECK: cir.store %arg0, %[[#V1]] : !s32i, !cir.ptr +// CHECK: %[[#V2:]] = cir.alloca !cir.ptr>, !cir.ptr>>, ["a", init] +// CHECK: %[[#V3:]] = cir.get_global @foo : !cir.ptr> +// CHECK: %[[#V4:]] = cir.cast(bitcast, %[[#V3]] : !cir.ptr>), !cir.ptr> +// CHECK: cir.store %[[#V4]], %[[#V2]] : !cir.ptr>, !cir.ptr>> +// CHECK: %[[#V5:]] = cir.load %[[#V2]] : !cir.ptr>>, !cir.ptr> +// CHECK: %[[#V6:]] = cir.cast(bitcast, %[[#V0]] : !cir.ptr), !cir.ptr +// CHECK: %[[#V7:]] = cir.load %[[#V6]] : !cir.ptr, !s32i +// CHECK: %[[#V8:]] = cir.cast(bitcast, %[[#V5]] : !cir.ptr>), !cir.ptr> +// CHECK: %[[#V9:]] = cir.call %[[#V8]](%[[#V7]]) : (!cir.ptr>, !s32i) -> !s32i + +// LLVM: define dso_local void @baz(i32 %0) +// LLVM: %[[#V1:]] = alloca %struct.S, i64 1 +// LLVM: store i32 %0, ptr %[[#V1]] +// LLVM: %[[#V2:]] = alloca ptr, i64 1 +// LLVM: store ptr @foo, ptr %[[#V2]] +// LLVM: %[[#V3:]] = load ptr, ptr %[[#V2]] +// LLVM: %[[#V4:]] = load i32, ptr %[[#V1]] +// LLVM: %[[#V5:]] = call i32 %[[#V3]](i32 %[[#V4]]) + +void baz(S s) { + myfptr a = foo; + a(s); +} From c7f174737d9c53c2f4c5c5304b40fbc8cda67acd Mon Sep 17 00:00:00 2001 From: gitoleg Date: Thu, 31 Oct 2024 13:37:34 +0300 Subject: [PATCH 2/3] refactoring --- .../Transforms/TargetLowering/LowerFunction.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp index 7676815cf847..e987d159c2da 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp @@ -832,16 +832,21 @@ Value LowerFunction::rewriteCallOp(const LowerFunctionInfo &CallInfo, // NOTE(cir): We don't know if the callee was already lowered, so we only // fetch the name from the callee, while the return type is fetch from the // lowering types manager. + + CallOp newCallOp; + if (Caller.isIndirect()) { rewriter.setInsertionPoint(Caller); auto val = Caller.getIndirectCall(); auto ptrTy = PointerType::get(val.getContext(), IRFuncTy); - auto callee = rewriter.create(val.getLoc(), ptrTy, CastKind::bitcast, val); - IRCallArgs.insert(IRCallArgs.begin(), callee); + auto callee = rewriter.create( + val.getLoc(), ptrTy, CastKind::bitcast, val); + newCallOp = rewriter.create(loc, callee, IRFuncTy, IRCallArgs); + } else { + newCallOp = rewriter.create( + loc, Caller.getCalleeAttr(), IRFuncTy.getReturnType(), IRCallArgs); } - CallOp newCallOp = rewriter.create( - loc, Caller.getCalleeAttr(), IRFuncTy.getReturnType(), IRCallArgs); auto extraAttrs = rewriter.getAttr(rewriter.getDictionaryAttr({})); newCallOp->setAttr("extra_attrs", extraAttrs); From 8d72eda30d2763f23865383fcb334da352047f56 Mon Sep 17 00:00:00 2001 From: gitoleg Date: Thu, 31 Oct 2024 13:55:30 +0300 Subject: [PATCH 3/3] clang-format ... --- .../Transforms/TargetLowering/LowerFunction.cpp | 10 +++++----- .../Dialect/Transforms/TargetLowering/LowerModule.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp index e987d159c2da..1942b5b1bb5a 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp @@ -832,19 +832,19 @@ Value LowerFunction::rewriteCallOp(const LowerFunctionInfo &CallInfo, // NOTE(cir): We don't know if the callee was already lowered, so we only // fetch the name from the callee, while the return type is fetch from the // lowering types manager. - + CallOp newCallOp; if (Caller.isIndirect()) { rewriter.setInsertionPoint(Caller); auto val = Caller.getIndirectCall(); auto ptrTy = PointerType::get(val.getContext(), IRFuncTy); - auto callee = rewriter.create( - val.getLoc(), ptrTy, CastKind::bitcast, val); + auto callee = + rewriter.create(val.getLoc(), ptrTy, CastKind::bitcast, val); newCallOp = rewriter.create(loc, callee, IRFuncTy, IRCallArgs); } else { - newCallOp = rewriter.create( - loc, Caller.getCalleeAttr(), IRFuncTy.getReturnType(), IRCallArgs); + newCallOp = rewriter.create(loc, Caller.getCalleeAttr(), + IRFuncTy.getReturnType(), IRCallArgs); } auto extraAttrs = diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h index 01a3dc273c94..07e74fe4dc51 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h @@ -96,7 +96,7 @@ class LowerModule { LogicalResult rewriteFunctionDefinition(FuncOp op); // Rewrite CIR CallOp to match the target ABI. - LogicalResult rewriteFunctionCall(CallOp callOp, FuncOp funcOp={}); + LogicalResult rewriteFunctionCall(CallOp callOp, FuncOp funcOp = {}); }; std::unique_ptr createLowerModule(ModuleOp module,