Skip to content

Commit 628a3f0

Browse files
authored
[CIR] Call to variadic functions (#141942)
1 parent 4efc13f commit 628a3f0

File tree

6 files changed

+50
-7
lines changed

6 files changed

+50
-7
lines changed

clang/include/clang/CIR/MissingFeatures.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@ struct MissingFeatures {
9999
static bool opCallAttrs() { return false; }
100100
static bool opCallSurroundingTry() { return false; }
101101
static bool opCallASTAttr() { return false; }
102-
static bool opCallVariadic() { return false; }
103102
static bool opCallObjCMethod() { return false; }
104103
static bool opCallExtParameterInfo() { return false; }
105104
static bool opCallCIRGenFuncInfoParamInfo() { return false; }

clang/lib/CIR/CodeGen/CIRGenCall.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm,
122122

123123
if (const auto *proto = dyn_cast<FunctionProtoType>(fnType)) {
124124
if (proto->isVariadic())
125-
cgm.errorNYI("call to variadic function");
125+
required = RequiredArgs::getFromProtoWithExtraSlots(proto, 0);
126126
if (proto->hasExtParameterInfos())
127127
cgm.errorNYI("call to functions with extra parameter info");
128128
} else if (cgm.getTargetCIRGenInfo().isNoProtoCallVariadic(
@@ -409,6 +409,18 @@ void CIRGenFunction::emitCallArg(CallArgList &args, const clang::Expr *e,
409409
args.add(emitAnyExprToTemp(e), argType);
410410
}
411411

412+
QualType CIRGenFunction::getVarArgType(const Expr *arg) {
413+
// System headers on Windows define NULL to 0 instead of 0LL on Win64. MSVC
414+
// implicitly widens null pointer constants that are arguments to varargs
415+
// functions to pointer-sized ints.
416+
if (!getTarget().getTriple().isOSWindows())
417+
return arg->getType();
418+
419+
assert(!cir::MissingFeatures::msabi());
420+
cgm.errorNYI(arg->getSourceRange(), "getVarArgType: NYI for Windows target");
421+
return arg->getType();
422+
}
423+
412424
/// Similar to emitAnyExpr(), however, the result will always be accessible
413425
/// even if no aggregate location is provided.
414426
RValue CIRGenFunction::emitAnyExprToTemp(const Expr *e) {
@@ -429,18 +441,20 @@ void CIRGenFunction::emitCallArgs(
429441
assert(!cir::MissingFeatures::opCallCallConv());
430442

431443
// First, if a prototype was provided, use those argument types.
432-
assert(!cir::MissingFeatures::opCallVariadic());
444+
bool isVariadic = false;
433445
if (prototype.p) {
434446
assert(!cir::MissingFeatures::opCallObjCMethod());
435447

436448
const auto *fpt = cast<const FunctionProtoType *>(prototype.p);
449+
isVariadic = fpt->isVariadic();
450+
assert(!cir::MissingFeatures::opCallCallConv());
437451
argTypes.assign(fpt->param_type_begin() + paramsToSkip,
438452
fpt->param_type_end());
439453
}
440454

441455
// If we still have any arguments, emit them using the type of the argument.
442456
for (const clang::Expr *a : llvm::drop_begin(argRange, argTypes.size()))
443-
argTypes.push_back(a->getType());
457+
argTypes.push_back(isVariadic ? getVarArgType(a) : a->getType());
444458
assert(argTypes.size() == (size_t)(argRange.end() - argRange.begin()));
445459

446460
// We must evaluate arguments from right to left in the MS C++ ABI, because

clang/lib/CIR/CodeGen/CIRGenFunction.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ class CIRGenFunction : public CIRGenTypeCache {
106106

107107
CIRGenTypes &getTypes() const { return cgm.getTypes(); }
108108

109+
const TargetInfo &getTarget() const { return cgm.getTarget(); }
109110
mlir::MLIRContext &getMLIRContext() { return cgm.getMLIRContext(); }
110111

111112
private:
@@ -791,6 +792,9 @@ class CIRGenFunction : public CIRGenTypeCache {
791792

792793
void emitOpenACCDeclare(const OpenACCDeclareDecl &d);
793794
void emitOpenACCRoutine(const OpenACCRoutineDecl &d);
795+
796+
private:
797+
QualType getVarArgType(const Expr *arg);
794798
};
795799

796800
} // namespace clang::CIRGen

clang/lib/CIR/Dialect/IR/CIRDialect.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -609,10 +609,10 @@ verifyCallCommInSymbolUses(mlir::Operation *op,
609609
unsigned numCallOperands = callIf.getNumArgOperands();
610610
unsigned numFnOpOperands = fnType.getNumInputs();
611611

612-
assert(!cir::MissingFeatures::opCallVariadic());
613-
614-
if (numCallOperands != numFnOpOperands)
612+
if (!fnType.isVarArg() && numCallOperands != numFnOpOperands)
615613
return op->emitOpError("incorrect number of operands for callee");
614+
if (fnType.isVarArg() && numCallOperands < numFnOpOperands)
615+
return op->emitOpError("too few operands for callee");
616616

617617
for (unsigned i = 0, e = numFnOpOperands; i != e; ++i)
618618
if (callIf.getArgOperand(i).getType() != fnType.getInput(i))

clang/test/CIR/CodeGen/call.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,17 @@ int f7(int (*ptr)(int, int)) {
5656
// LLVM-LABEL: define i32 @_Z2f7PFiiiE
5757
// LLVM: %[[#ptr:]] = load ptr, ptr %{{.+}}
5858
// LLVM-NEXT: %{{.+}} = call i32 %[[#ptr]](i32 1, i32 2)
59+
60+
void f8(int a, ...);
61+
void f9() {
62+
f8(1);
63+
f8(1, 2, 3, 4);
64+
}
65+
66+
// CIR-LABEL: cir.func @_Z2f9v()
67+
// CIR: cir.call @_Z2f8iz(%{{.+}}) : (!s32i) -> ()
68+
// CIR: cir.call @_Z2f8iz(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}}) : (!s32i, !s32i, !s32i, !s32i) -> ()
69+
70+
// LLVM-LABEL: define void @_Z2f9v()
71+
// LLVM: call void (i32, ...) @_Z2f8iz(i32 1)
72+
// LLVM: call void (i32, ...) @_Z2f8iz(i32 1, i32 2, i32 3, i32 4)

clang/test/CIR/IR/invalid-call.cir

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,15 @@ cir.func @f11() {
6868
cir.call @f10(%0, %1) : (!s32i, !u32i) -> ()
6969
cir.return
7070
}
71+
72+
// -----
73+
74+
!s32i = !cir.int<s, 32>
75+
76+
cir.func @f12(!s32i, !s32i, ...)
77+
cir.func @f13() {
78+
%0 = cir.const #cir.int<1> : !s32i
79+
// expected-error @below {{too few operands for callee}}
80+
cir.call @f12(%0) : (!s32i) -> ()
81+
cir.return
82+
}

0 commit comments

Comments
 (0)