[clang] [CIR] Upstream initial function call support (PR #134673)
Bruno Cardoso Lopes via cfe-commits
cfe-commits at lists.llvm.org
Wed Apr 9 11:07:52 PDT 2025
================
@@ -304,6 +305,102 @@ RValue CIRGenFunction::emitAnyExpr(const Expr *e) {
llvm_unreachable("bad evaluation kind");
}
+static cir::FuncOp emitFunctionDeclPointer(CIRGenModule &cgm, GlobalDecl gd) {
+ assert(!cir::MissingFeatures::weakRefReference());
+ return cgm.getAddrOfFunction(gd);
+}
+
+static CIRGenCallee emitDirectCallee(CIRGenModule &cgm, GlobalDecl gd) {
+ assert(!cir::MissingFeatures::opCallBuiltinFunc());
+
+ cir::FuncOp callee = emitFunctionDeclPointer(cgm, gd);
+
+ assert(!cir::MissingFeatures::hip());
+
+ return CIRGenCallee::forDirect(callee, gd);
+}
+
+RValue CIRGenFunction::emitCall(clang::QualType calleeTy,
+ const CIRGenCallee &callee,
+ const clang::CallExpr *e) {
+ // Get the actual function type. The callee type will always be a pointer to
+ // function type or a block pointer type.
+ assert(calleeTy->isFunctionPointerType() &&
+ "Callee must have function pointer type!");
+
+ calleeTy = getContext().getCanonicalType(calleeTy);
+
+ if (getLangOpts().CPlusPlus)
+ assert(!cir::MissingFeatures::sanitizers());
+
+ assert(!cir::MissingFeatures::sanitizers());
+ assert(!cir::MissingFeatures::opCallArgs());
+
+ const CIRGenFunctionInfo &funcInfo = cgm.getTypes().arrangeFreeFunctionCall();
+
+ assert(!cir::MissingFeatures::opCallNoPrototypeFunc());
+ assert(!cir::MissingFeatures::opCallChainCall());
+ assert(!cir::MissingFeatures::hip());
+ assert(!cir::MissingFeatures::opCallMustTail());
+
+ cir::CIRCallOpInterface callOp;
+ RValue callResult =
+ emitCall(funcInfo, callee, &callOp, getLoc(e->getExprLoc()));
+
+ assert(!cir::MissingFeatures::generateDebugInfo());
+
+ return callResult;
+}
+
+CIRGenCallee CIRGenFunction::emitCallee(const clang::Expr *e) {
+ e = e->IgnoreParens();
+
+ // Look through function-to-pointer decay.
+ if (const auto *implicitCast = dyn_cast<ImplicitCastExpr>(e)) {
+ if (implicitCast->getCastKind() == CK_FunctionToPointerDecay ||
+ implicitCast->getCastKind() == CK_BuiltinFnToFnPtr) {
+ return emitCallee(implicitCast->getSubExpr());
+ }
+ // Resolve direct calls.
+ } else if (const auto *declRef = dyn_cast<DeclRefExpr>(e)) {
+ const auto *funcDecl = dyn_cast<FunctionDecl>(declRef->getDecl());
+ assert(
+ funcDecl &&
+ "DeclRef referring to FunctionDecl is the only thing supported so far");
+ return emitDirectCallee(cgm, funcDecl);
+ }
+
+ llvm_unreachable("Nothing else supported yet!");
+}
+
+RValue CIRGenFunction::emitCallExpr(const clang::CallExpr *e) {
+ assert(!cir::MissingFeatures::objCBlocks());
+
+ if (isa<CXXMemberCallExpr>(e)) {
+ cgm.errorNYI(e->getSourceRange(), "call to member function");
+ return RValue::get(nullptr);
+ }
+
+ if (isa<CUDAKernelCallExpr>(e)) {
+ cgm.errorNYI(e->getSourceRange(), "call to CUDA kernel");
+ return RValue::get(nullptr);
+ }
+
+ if (const auto *operatorCall = dyn_cast<CXXOperatorCallExpr>(e)) {
+ if (isa_and_nonnull<CXXMethodDecl>(operatorCall->getCalleeDecl())) {
+ cgm.errorNYI(e->getSourceRange(), "call to member operator");
+ return RValue::get(nullptr);
+ }
+ }
+
+ CIRGenCallee callee = emitCallee(e->getCallee());
+
----------------
bcardosolopes wrote:
> The fact that compilation continues after errorNYI is one of the reasons it is preferred. We want to be able to continue compiling so we can see what problems may lie beyond the unimplemented code
One extra advantage is being able to write tests with `-verify` and use `expected-error` for features.
https://github.com/llvm/llvm-project/pull/134673
More information about the cfe-commits
mailing list