[clang] 628a3f0 - [CIR] Call to variadic functions (#141942)
via cfe-commits
cfe-commits at lists.llvm.org
Fri May 30 18:59:45 PDT 2025
Author: Sirui Mu
Date: 2025-05-31T09:59:41+08:00
New Revision: 628a3f0a48fcdf9485a051a4b9d64888b9b21143
URL: https://github.com/llvm/llvm-project/commit/628a3f0a48fcdf9485a051a4b9d64888b9b21143
DIFF: https://github.com/llvm/llvm-project/commit/628a3f0a48fcdf9485a051a4b9d64888b9b21143.diff
LOG: [CIR] Call to variadic functions (#141942)
Added:
Modified:
clang/include/clang/CIR/MissingFeatures.h
clang/lib/CIR/CodeGen/CIRGenCall.cpp
clang/lib/CIR/CodeGen/CIRGenFunction.h
clang/lib/CIR/Dialect/IR/CIRDialect.cpp
clang/test/CIR/CodeGen/call.cpp
clang/test/CIR/IR/invalid-call.cir
Removed:
################################################################################
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index 11250be483edc..b8a40666a98c6 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -99,7 +99,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 76860191de7bb..36f050de9f8bb 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -609,10 +609,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
+}
More information about the cfe-commits
mailing list