https://github.com/Lancern updated https://github.com/llvm/llvm-project/pull/141942
>From 862cb3bd98bc2ed6a6b01efe0f08ebfaf8ad63e0 Mon Sep 17 00:00:00 2001 From: Sirui Mu <msrlanc...@gmail.com> Date: Thu, 29 May 2025 17:21:06 +0800 Subject: [PATCH] [CIR] Call to variadic functions --- clang/include/clang/CIR/MissingFeatures.h | 1 - clang/lib/CIR/CodeGen/CIRGenCall.cpp | 20 +++++++++++++++++--- clang/lib/CIR/CodeGen/CIRGenFunction.h | 4 ++++ clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 6 +++--- clang/test/CIR/CodeGen/call.cpp | 14 ++++++++++++++ clang/test/CIR/IR/invalid-call.cir | 12 ++++++++++++ 6 files changed, 50 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h index 56bf9b1130f12..f7385a672f6af 100644 --- a/clang/include/clang/CIR/MissingFeatures.h +++ b/clang/include/clang/CIR/MissingFeatures.h @@ -100,7 +100,6 @@ struct MissingFeatures { static bool opCallAttrs() { return false; } static bool opCallSurroundingTry() { return false; } static bool opCallASTAttr() { return false; } - static bool opCallVariadic() { return false; } static bool opCallObjCMethod() { return false; } static bool opCallExtParameterInfo() { return false; } static bool opCallCIRGenFuncInfoParamInfo() { return false; } diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp index 1317f8c6c073a..b194a8670bfb9 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp @@ -122,7 +122,7 @@ arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm, if (const auto *proto = dyn_cast<FunctionProtoType>(fnType)) { if (proto->isVariadic()) - cgm.errorNYI("call to variadic function"); + required = RequiredArgs::getFromProtoWithExtraSlots(proto, 0); if (proto->hasExtParameterInfos()) cgm.errorNYI("call to functions with extra parameter info"); } else if (cgm.getTargetCIRGenInfo().isNoProtoCallVariadic( @@ -409,6 +409,18 @@ void CIRGenFunction::emitCallArg(CallArgList &args, const clang::Expr *e, args.add(emitAnyExprToTemp(e), argType); } +QualType CIRGenFunction::getVarArgType(const Expr *arg) { + // System headers on Windows define NULL to 0 instead of 0LL on Win64. MSVC + // implicitly widens null pointer constants that are arguments to varargs + // functions to pointer-sized ints. + if (!getTarget().getTriple().isOSWindows()) + return arg->getType(); + + assert(!cir::MissingFeatures::msabi()); + cgm.errorNYI(arg->getSourceRange(), "getVarArgType: NYI for Windows target"); + return arg->getType(); +} + /// Similar to emitAnyExpr(), however, the result will always be accessible /// even if no aggregate location is provided. RValue CIRGenFunction::emitAnyExprToTemp(const Expr *e) { @@ -429,18 +441,20 @@ void CIRGenFunction::emitCallArgs( assert(!cir::MissingFeatures::opCallCallConv()); // First, if a prototype was provided, use those argument types. - assert(!cir::MissingFeatures::opCallVariadic()); + bool isVariadic = false; if (prototype.p) { assert(!cir::MissingFeatures::opCallObjCMethod()); const auto *fpt = cast<const FunctionProtoType *>(prototype.p); + isVariadic = fpt->isVariadic(); + assert(!cir::MissingFeatures::opCallCallConv()); argTypes.assign(fpt->param_type_begin() + paramsToSkip, fpt->param_type_end()); } // If we still have any arguments, emit them using the type of the argument. for (const clang::Expr *a : llvm::drop_begin(argRange, argTypes.size())) - argTypes.push_back(a->getType()); + argTypes.push_back(isVariadic ? getVarArgType(a) : a->getType()); assert(argTypes.size() == (size_t)(argRange.end() - argRange.begin())); // We must evaluate arguments from right to left in the MS C++ ABI, because diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index 74f2e4043933d..0badde024b166 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -106,6 +106,7 @@ class CIRGenFunction : public CIRGenTypeCache { CIRGenTypes &getTypes() const { return cgm.getTypes(); } + const TargetInfo &getTarget() const { return cgm.getTarget(); } mlir::MLIRContext &getMLIRContext() { return cgm.getMLIRContext(); } private: @@ -791,6 +792,9 @@ class CIRGenFunction : public CIRGenTypeCache { void emitOpenACCDeclare(const OpenACCDeclareDecl &d); void emitOpenACCRoutine(const OpenACCRoutineDecl &d); + +private: + QualType getVarArgType(const Expr *arg); }; } // namespace clang::CIRGen diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 9e2b2908b22d8..3e6d22879a78c 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -601,10 +601,10 @@ verifyCallCommInSymbolUses(mlir::Operation *op, unsigned numCallOperands = callIf.getNumArgOperands(); unsigned numFnOpOperands = fnType.getNumInputs(); - assert(!cir::MissingFeatures::opCallVariadic()); - - if (numCallOperands != numFnOpOperands) + if (!fnType.isVarArg() && numCallOperands != numFnOpOperands) return op->emitOpError("incorrect number of operands for callee"); + if (fnType.isVarArg() && numCallOperands < numFnOpOperands) + return op->emitOpError("too few operands for callee"); for (unsigned i = 0, e = numFnOpOperands; i != e; ++i) if (callIf.getArgOperand(i).getType() != fnType.getInput(i)) diff --git a/clang/test/CIR/CodeGen/call.cpp b/clang/test/CIR/CodeGen/call.cpp index 792f57afd6bd1..741cadeb5c764 100644 --- a/clang/test/CIR/CodeGen/call.cpp +++ b/clang/test/CIR/CodeGen/call.cpp @@ -56,3 +56,17 @@ int f7(int (*ptr)(int, int)) { // LLVM-LABEL: define i32 @_Z2f7PFiiiE // LLVM: %[[#ptr:]] = load ptr, ptr %{{.+}} // LLVM-NEXT: %{{.+}} = call i32 %[[#ptr]](i32 1, i32 2) + +void f8(int a, ...); +void f9() { + f8(1); + f8(1, 2, 3, 4); +} + +// CIR-LABEL: cir.func @_Z2f9v() +// CIR: cir.call @_Z2f8iz(%{{.+}}) : (!s32i) -> () +// CIR: cir.call @_Z2f8iz(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) : (!s32i, !s32i, !s32i, !s32i) -> () + +// LLVM-LABEL: define void @_Z2f9v() +// LLVM: call void (i32, ...) @_Z2f8iz(i32 1) +// LLVM: call void (i32, ...) @_Z2f8iz(i32 1, i32 2, i32 3, i32 4) diff --git a/clang/test/CIR/IR/invalid-call.cir b/clang/test/CIR/IR/invalid-call.cir index 8a584bae70878..3ebb771ed72e7 100644 --- a/clang/test/CIR/IR/invalid-call.cir +++ b/clang/test/CIR/IR/invalid-call.cir @@ -68,3 +68,15 @@ cir.func @f11() { cir.call @f10(%0, %1) : (!s32i, !u32i) -> () cir.return } + +// ----- + +!s32i = !cir.int<s, 32> + +cir.func @f12(!s32i, !s32i, ...) +cir.func @f13() { + %0 = cir.const #cir.int<1> : !s32i + // expected-error @below {{too few operands for callee}} + cir.call @f12(%0) : (!s32i) -> () + cir.return +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits