Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[CIR][NFC] Use arrangeFunctionDeclaration to build function types #139787

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 63 additions & 14 deletions 77 clang/lib/CIR/CodeGen/CIRGenCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,11 @@ CIRGenFunctionInfo::create(CanQualType resultType,

cir::FuncType CIRGenTypes::getFunctionType(const CIRGenFunctionInfo &fi) {
mlir::Type resultType = convertType(fi.getReturnType());
SmallVector<mlir::Type, 8> argTypes;
argTypes.reserve(fi.getNumRequiredArgs());

SmallVector<mlir::Type, 8> argTypes(fi.getNumRequiredArgs());

unsigned argNo = 0;
llvm::ArrayRef<CIRGenFunctionInfoArgInfo> argInfos(fi.argInfoBegin(),
fi.getNumRequiredArgs());
for (const auto &argInfo : argInfos)
argTypes[argNo++] = convertType(argInfo.type);
for (const CIRGenFunctionInfoArgInfo &argInfo : fi.requiredArguments())
argTypes.push_back(convertType(argInfo.type));

return cir::FuncType::get(argTypes,
(resultType ? resultType : builder.getVoidTy()),
Expand All @@ -63,6 +60,35 @@ CIRGenCallee CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const {
return *this;
}

/// Adds the formal parameters in FPT to the given prefix. If any parameter in
/// FPT has pass_object_size_attrs, then we'll add parameters for those, too.
/// TODO(cir): this should be shared with LLVM codegen
static void appendParameterTypes(const CIRGenTypes &cgt,
SmallVectorImpl<CanQualType> &prefix,
CanQual<FunctionProtoType> fpt) {
assert(!cir::MissingFeatures::opCallExtParameterInfo());
// Fast path: don't touch param info if we don't need to.
if (!fpt->hasExtParameterInfos()) {
prefix.append(fpt->param_type_begin(), fpt->param_type_end());
return;
}

cgt.getCGModule().errorNYI("appendParameterTypes: hasExtParameterInfos");
}

/// Arrange the CIR function layout for a value of the given function type, on
/// top of any implicit parameters already stored.
static const CIRGenFunctionInfo &
arrangeCIRFunctionInfo(CIRGenTypes &cgt, SmallVectorImpl<CanQualType> &prefix,
CanQual<FunctionProtoType> ftp) {
RequiredArgs required =
RequiredArgs::getFromProtoWithExtraSlots(ftp, prefix.size());
assert(!cir::MissingFeatures::opCallExtParameterInfo());
appendParameterTypes(cgt, prefix, ftp);
CanQualType resultType = ftp->getReturnType().getUnqualifiedType();
return cgt.arrangeCIRFunctionInfo(resultType, prefix, required);
}

static const CIRGenFunctionInfo &
arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm,
const CallArgList &args,
Expand Down Expand Up @@ -95,6 +121,34 @@ CIRGenTypes::arrangeFreeFunctionCall(const CallArgList &args,
return arrangeFreeFunctionLikeCall(*this, cgm, args, fnType);
}

/// Arrange the argument and result information for the declaration or
/// definition of the given function.
const CIRGenFunctionInfo &
CIRGenTypes::arrangeFunctionDeclaration(const FunctionDecl *fd) {
if (const auto *md = dyn_cast<CXXMethodDecl>(fd)) {
if (md->isInstance()) {
cgm.errorNYI("arrangeFunctionDeclaration: instance method");
}
}

CanQualType funcTy = fd->getType()->getCanonicalTypeUnqualified();

assert(isa<FunctionType>(funcTy));
// TODO: setCUDAKernelCallingConvention
erichkeane marked this conversation as resolved.
Show resolved Hide resolved
assert(!cir::MissingFeatures::cudaSupport());

// When declaring a function without a prototype, always use a non-variadic
// type.
if (CanQual<FunctionNoProtoType> noProto =
funcTy.getAs<FunctionNoProtoType>()) {
assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo());
return arrangeCIRFunctionInfo(noProto->getReturnType(), std::nullopt,
RequiredArgs::All);
}

return arrangeFreeFunctionType(funcTy.castAs<FunctionProtoType>());
}

static cir::CIRCallOpInterface
emitCallLikeOp(CIRGenFunction &cgf, mlir::Location callLoc,
cir::FuncOp directFuncOp,
Expand All @@ -112,13 +166,8 @@ emitCallLikeOp(CIRGenFunction &cgf, mlir::Location callLoc,

const CIRGenFunctionInfo &
CIRGenTypes::arrangeFreeFunctionType(CanQual<FunctionProtoType> fpt) {
SmallVector<CanQualType, 8> argTypes;
for (unsigned i = 0, e = fpt->getNumParams(); i != e; ++i)
argTypes.push_back(fpt->getParamType(i));
RequiredArgs required = RequiredArgs::forPrototypePlus(fpt);

CanQualType resultType = fpt->getReturnType().getUnqualifiedType();
return arrangeCIRFunctionInfo(resultType, argTypes, required);
SmallVector<CanQualType, 16> argTypes;
return ::arrangeCIRFunctionInfo(*this, argTypes, fpt);
}

const CIRGenFunctionInfo &
Expand Down
18 changes: 14 additions & 4 deletions 18 clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,21 @@ class RequiredArgs {
///
/// If FD is not null, this will consider pass_object_size params in FD.
static RequiredArgs
forPrototypePlus(const clang::FunctionProtoType *prototype) {
getFromProtoWithExtraSlots(const clang::FunctionProtoType *prototype,
unsigned additional) {
if (!prototype->isVariadic())
return All;

if (prototype->hasExtParameterInfos())
llvm_unreachable("NYI");

return RequiredArgs(prototype->getNumParams());
return RequiredArgs(prototype->getNumParams() + additional);
}

static RequiredArgs
forPrototypePlus(clang::CanQual<clang::FunctionProtoType> prototype) {
return forPrototypePlus(prototype.getTypePtr());
getFromProtoWithExtraSlots(clang::CanQual<clang::FunctionProtoType> prototype,
unsigned additional) {
return getFromProtoWithExtraSlots(prototype.getTypePtr(), additional);
}

unsigned getNumRequiredArgs() const {
Expand Down Expand Up @@ -114,6 +116,14 @@ class CIRGenFunctionInfo final
getReturnType().Profile(id);
}

llvm::ArrayRef<ArgInfo> arguments() const {
return llvm::ArrayRef<ArgInfo>(argInfoBegin(), numArgs);
}

llvm::ArrayRef<ArgInfo> requiredArguments() const {
return llvm::ArrayRef<ArgInfo>(argInfoBegin(), getNumRequiredArgs());
}

CanQualType getReturnType() const { return getArgsBuffer()[0].type; }

const_arg_iterator argInfoBegin() const { return getArgsBuffer() + 1; }
Expand Down
17 changes: 2 additions & 15 deletions 17 clang/lib/CIR/CodeGen/CIRGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -249,21 +249,8 @@ void CIRGenModule::emitGlobalFunctionDefinition(clang::GlobalDecl gd,
return;
}

cir::FuncType funcType;
// TODO: Move this to arrangeFunctionDeclaration when it is
// implemented.
// When declaring a function without a prototype, always use a
// non-variadic type.
if (CanQual<FunctionNoProtoType> noProto =
funcDecl->getType()
->getCanonicalTypeUnqualified()
.getAs<FunctionNoProtoType>()) {
const CIRGenFunctionInfo &fi = getTypes().arrangeCIRFunctionInfo(
noProto->getReturnType(), {}, RequiredArgs::All);
funcType = getTypes().getFunctionType(fi);
} else {
funcType = cast<cir::FuncType>(convertType(funcDecl->getType()));
}
const CIRGenFunctionInfo &fi = getTypes().arrangeGlobalDeclaration(gd);
cir::FuncType funcType = getTypes().getFunctionType(fi);

cir::FuncOp funcOp = dyn_cast_if_present<cir::FuncOp>(op);
if (!funcOp || funcOp.getFunctionType() != funcType) {
Expand Down
14 changes: 14 additions & 0 deletions 14 clang/lib/CIR/CodeGen/CIRGenTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -553,3 +553,17 @@ CIRGenTypes::arrangeCIRFunctionInfo(CanQualType returnType,

return *fi;
}

const CIRGenFunctionInfo &CIRGenTypes::arrangeGlobalDeclaration(GlobalDecl gd) {
assert(!dyn_cast<ObjCMethodDecl>(gd.getDecl()) &&
"This is reported as a FIXME in LLVM codegen");
const auto *fd = cast<FunctionDecl>(gd.getDecl());

if (isa<CXXConstructorDecl>(gd.getDecl()) ||
isa<CXXDestructorDecl>(gd.getDecl())) {
cgm.errorNYI(SourceLocation(),
"arrangeGlobalDeclaration for C++ constructor or destructor");
}

return arrangeFunctionDeclaration(fd);
}
32 changes: 30 additions & 2 deletions 32 clang/lib/CIR/CodeGen/CIRGenTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,36 @@ class CIRGenTypes {
// TODO: convert this comment to account for MLIR's equivalence
mlir::Type convertTypeForMem(clang::QualType, bool forBitField = false);

/// Get the CIR function type for \arg Info.
cir::FuncType getFunctionType(const CIRGenFunctionInfo &info);

// The arrangement methods are split into three families:
// - those meant to drive the signature and prologue/epilogue
// of a function declaration or definition,
// - those meant for the computation of the CIR type for an abstract
// appearance of a function, and
// - those meant for performing the CIR-generation of a call.
// They differ mainly in how they deal with optional (i.e. variadic)
// arguments, as well as unprototyped functions.
//
// Key points:
// - The CIRGenFunctionInfo for emitting a specific call site must include
// entries for the optional arguments.
// - The function type used at the call site must reflect the formal
// signature
// of the declaration being called, or else the call will go away.
// - For the most part, unprototyped functions are called by casting to a
// formal signature inferred from the specific argument types used at the
// call-site. However, some targets (e.g. x86-64) screw with this for
// compatability reasons.

const CIRGenFunctionInfo &arrangeGlobalDeclaration(GlobalDecl gd);

/// Free functions are functions that are compatible with an ordinary C
/// function pointer type.
const CIRGenFunctionInfo &
arrangeFunctionDeclaration(const clang::FunctionDecl *fd);

/// Return whether a type can be zero-initialized (in the C++ sense) with an
/// LLVM zeroinitializer.
bool isZeroInitializable(clang::QualType ty);
Expand All @@ -134,8 +164,6 @@ class CIRGenTypes {
arrangeFreeFunctionType(CanQual<FunctionProtoType> fpt);
const CIRGenFunctionInfo &
arrangeFreeFunctionType(CanQual<FunctionNoProtoType> fnpt);

cir::FuncType getFunctionType(const CIRGenFunctionInfo &fi);
};

} // namespace clang::CIRGen
Expand Down
Morty Proxy This is a proxified and sanitized view of the page, visit original site.