[clang] [CIR] Cleanup support for C functions (PR #136854)
Iris Shi via cfe-commits
cfe-commits at lists.llvm.org
Thu Apr 24 03:51:38 PDT 2025
https://github.com/el-ev updated https://github.com/llvm/llvm-project/pull/136854
>From fd1d37ebf0f1c4a23f573444f30730b0f65630bf Mon Sep 17 00:00:00 2001
From: Iris Shi <0.0 at owo.li>
Date: Wed, 23 Apr 2025 20:23:09 +0800
Subject: [PATCH 1/2] [CIR] Cleanup support for C functions
---
clang/lib/CIR/CodeGen/CIRGenCall.cpp | 82 +++++++++++++++++++-
clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h | 90 +++++++++++++++++++++-
clang/lib/CIR/CodeGen/CIRGenModule.cpp | 17 +++-
clang/lib/CIR/CodeGen/CIRGenTypes.cpp | 37 ++++-----
clang/lib/CIR/CodeGen/CIRGenTypes.h | 12 ++-
clang/lib/CIR/CodeGen/TargetInfo.cpp | 10 ++-
clang/test/CIR/CodeGen/basic.c | 13 ++++
7 files changed, 232 insertions(+), 29 deletions(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index 69266f79a88a5..b223bc494f928 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -13,20 +13,76 @@
#include "CIRGenCall.h"
#include "CIRGenFunction.h"
+#include "CIRGenFunctionInfo.h"
#include "clang/CIR/MissingFeatures.h"
using namespace clang;
using namespace clang::CIRGen;
-CIRGenFunctionInfo *CIRGenFunctionInfo::create(CanQualType resultType) {
- void *buffer = operator new(totalSizeToAlloc<ArgInfo>(1));
+CIRGenFunctionInfo *
+CIRGenFunctionInfo::create(CanQualType resultType,
+ llvm::ArrayRef<CanQualType> argTypes,
+ RequiredArgs required) {
+ void *buffer = operator new(totalSizeToAlloc<ArgInfo>(argTypes.size() + 1));
CIRGenFunctionInfo *fi = new (buffer) CIRGenFunctionInfo();
+
+ fi->required = required;
+ fi->numArgs = argTypes.size();
fi->getArgsBuffer()[0].type = resultType;
+ for (unsigned i = 0; i < argTypes.size(); ++i)
+ fi->getArgsBuffer()[i + 1].type = argTypes[i];
return fi;
}
+cir::FuncType CIRGenTypes::getFunctionType(const CIRGenFunctionInfo &fi) {
+ bool inserted = functionsBeingProcessed.insert(&fi).second;
+ assert(inserted && "Recursively being processed?");
+
+ mlir::Type resultType = nullptr;
+ const cir::ABIArgInfo &retAI = fi.getReturnInfo();
+
+ switch (retAI.getKind()) {
+ case cir::ABIArgInfo::Ignore:
+ // TODO(CIR): This should probably be the None type from the builtin
+ // dialect.
+ resultType = nullptr;
+ break;
+
+ case cir::ABIArgInfo::Direct:
+ resultType = retAI.getCoerceToType();
+ break;
+
+ default:
+ assert(false && "NYI");
+ }
+
+ SmallVector<mlir::Type, 8> argTypes;
+ unsigned argNo = 0;
+ CIRGenFunctionInfo::const_arg_iterator it = fi.arg_begin(),
+ ie = it + fi.getNumRequiredArgs();
+ for (; it != ie; ++it, ++argNo) {
+ const auto &argInfo = it->info;
+
+ switch (argInfo.getKind()) {
+ default:
+ llvm_unreachable("NYI");
+ case cir::ABIArgInfo::Direct:
+ mlir::Type argType = argInfo.getCoerceToType();
+ argTypes.push_back(argType);
+ break;
+ }
+ }
+
+ bool erased = functionsBeingProcessed.erase(&fi);
+ assert(erased && "Not in set?");
+
+ return cir::FuncType::get(argTypes,
+ (resultType ? resultType : builder.getVoidTy()),
+ fi.isVariadic());
+}
+
CIRGenCallee CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const {
assert(!cir::MissingFeatures::opCallVirtual());
return *this;
@@ -35,6 +91,9 @@ CIRGenCallee CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const {
static const CIRGenFunctionInfo &
arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm,
const FunctionType *fnType) {
+
+ RequiredArgs required = RequiredArgs::All;
+
if (const auto *proto = dyn_cast<FunctionProtoType>(fnType)) {
if (proto->isVariadic())
cgm.errorNYI("call to variadic function");
@@ -49,7 +108,7 @@ arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm,
CanQualType retType = fnType->getReturnType()
->getCanonicalTypeUnqualified()
.getUnqualifiedType();
- return cgt.arrangeCIRFunctionInfo(retType);
+ return cgt.arrangeCIRFunctionInfo(retType, {}, required);
}
const CIRGenFunctionInfo &
@@ -71,6 +130,23 @@ static cir::CIRCallOpInterface emitCallLikeOp(CIRGenFunction &cgf,
return builder.createCallOp(callLoc, directFuncOp);
}
+const CIRGenFunctionInfo &
+CIRGenTypes::arrangeFreeFunctionType(CanQual<FunctionProtoType> fpt) {
+ SmallVector<CanQualType, 16> 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);
+}
+
+const CIRGenFunctionInfo &
+CIRGenTypes::arrangeFreeFunctionType(CanQual<FunctionNoProtoType> fnpt) {
+ CanQualType resultType = fnpt->getReturnType().getUnqualifiedType();
+ return arrangeCIRFunctionInfo(resultType, {}, RequiredArgs(0));
+}
+
RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
const CIRGenCallee &callee,
ReturnValueSlot returnValue,
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h b/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h
index c4a2b238c96ae..f08fe46ad98a1 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h
@@ -27,17 +27,68 @@ struct CIRGenFunctionInfoArgInfo {
cir::ABIArgInfo info;
};
+/// A class for recording the number of arguments that a function signature
+/// requires.
+class RequiredArgs {
+ /// The number of required arguments, or ~0 if the signature does not permit
+ /// optional arguments.
+ unsigned numRequired;
+
+public:
+ enum All_t { All };
+
+ RequiredArgs(All_t _) : numRequired(~0U) {}
+ explicit RequiredArgs(unsigned n) : numRequired(n) { assert(n != ~0U); }
+
+ unsigned getOpaqueData() const { return numRequired; }
+
+ bool allowsOptionalArgs() const { return numRequired != ~0U; }
+
+ /// Compute the arguments required by the given formal prototype, given that
+ /// there may be some additional, non-formal arguments in play.
+ ///
+ /// If FD is not null, this will consider pass_object_size params in FD.
+ static RequiredArgs
+ forPrototypePlus(const clang::FunctionProtoType *prototype) {
+ if (!prototype->isVariadic())
+ return All;
+
+ if (prototype->hasExtParameterInfos())
+ llvm_unreachable("NYI");
+
+ return RequiredArgs(prototype->getNumParams());
+ }
+
+ static RequiredArgs
+ forPrototypePlus(clang::CanQual<clang::FunctionProtoType> prototype) {
+ return forPrototypePlus(prototype.getTypePtr());
+ }
+
+ unsigned getNumRequiredArgs() const {
+ assert(allowsOptionalArgs());
+ return numRequired;
+ }
+};
+
class CIRGenFunctionInfo final
: public llvm::FoldingSetNode,
private llvm::TrailingObjects<CIRGenFunctionInfo,
CIRGenFunctionInfoArgInfo> {
using ArgInfo = CIRGenFunctionInfoArgInfo;
+ RequiredArgs required;
+
+ unsigned numArgs;
+
ArgInfo *getArgsBuffer() { return getTrailingObjects<ArgInfo>(); }
const ArgInfo *getArgsBuffer() const { return getTrailingObjects<ArgInfo>(); }
+ CIRGenFunctionInfo() : required(RequiredArgs::All) {}
+
public:
- static CIRGenFunctionInfo *create(CanQualType resultType);
+ static CIRGenFunctionInfo *create(CanQualType resultType,
+ llvm::ArrayRef<CanQualType> argTypes,
+ RequiredArgs required);
void operator delete(void *p) { ::operator delete(p); }
@@ -47,11 +98,22 @@ class CIRGenFunctionInfo final
// This function has to be CamelCase because llvm::FoldingSet requires so.
// NOLINTNEXTLINE(readability-identifier-naming)
- static void Profile(llvm::FoldingSetNodeID &id, CanQualType resultType) {
+ static void Profile(llvm::FoldingSetNodeID &id, RequiredArgs required,
+ CanQualType resultType,
+ llvm::ArrayRef<CanQualType> argTypes) {
+ id.AddBoolean(required.getOpaqueData());
resultType.Profile(id);
+ for (const auto &arg : argTypes)
+ arg.Profile(id);
}
- void Profile(llvm::FoldingSetNodeID &id) { getReturnType().Profile(id); }
+ // NOLINTNEXTLINE(readability-identifier-naming)
+ void Profile(llvm::FoldingSetNodeID &id) {
+ id.AddBoolean(required.getOpaqueData());
+ getReturnType().Profile(id);
+ for (const auto &i : arguments())
+ i.type.Profile(id);
+ }
CanQualType getReturnType() const { return getArgsBuffer()[0].type; }
@@ -59,6 +121,28 @@ class CIRGenFunctionInfo final
const cir::ABIArgInfo &getReturnInfo() const {
return getArgsBuffer()[0].info;
}
+ using const_arg_iterator = const ArgInfo *;
+ using arg_iterator = ArgInfo *;
+
+ const_arg_iterator arg_begin() const { return getArgsBuffer() + 1; }
+ const_arg_iterator arg_end() const { return getArgsBuffer() + 1 + numArgs; }
+ arg_iterator arg_begin() { return getArgsBuffer() + 1; }
+ arg_iterator arg_end() { return getArgsBuffer() + 1 + numArgs; }
+
+ unsigned arg_size() const { return numArgs; }
+
+ llvm::MutableArrayRef<ArgInfo> arguments() {
+ return llvm::MutableArrayRef<ArgInfo>(arg_begin(), numArgs);
+ }
+ llvm::ArrayRef<ArgInfo> arguments() const {
+ return llvm::ArrayRef<ArgInfo>(arg_begin(), numArgs);
+ }
+
+ bool isVariadic() const { return required.allowsOptionalArgs(); }
+ RequiredArgs getRequiredArgs() const { return required; }
+ unsigned getNumRequiredArgs() const {
+ return isVariadic() ? getRequiredArgs().getNumRequiredArgs() : arg_size();
+ }
};
} // namespace clang::CIRGen
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 3b13d495be5e3..fad1416fa2225 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -212,8 +212,21 @@ void CIRGenModule::emitGlobalFunctionDefinition(clang::GlobalDecl gd,
"function definition with a non-identifier for a name");
return;
}
- cir::FuncType funcType =
- cast<cir::FuncType>(convertType(funcDecl->getType()));
+
+ 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>()) {
+ auto &fi = getTypes().arrangeCIRFunctionInfo(noProto->getReturnType(), {},
+ RequiredArgs::All);
+ funcType = getTypes().getFunctionType(fi);
+ } else
+ funcType = cast<cir::FuncType>(convertType(funcDecl->getType()));
cir::FuncOp funcOp = dyn_cast_if_present<cir::FuncOp>(op);
if (!funcOp || funcOp.getFunctionType() != funcType) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index b11f8466607f8..bf3d96af37936 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -73,21 +73,19 @@ mlir::Type CIRGenTypes::convertFunctionTypeInternal(QualType qft) {
return cir::FuncType::get(SmallVector<mlir::Type, 1>{}, cgm.VoidTy);
}
- // TODO(CIR): This is a stub of what the final code will be. See the
- // implementation of this function and the implementation of class
- // CIRGenFunction in the ClangIR incubator project.
-
+ const CIRGenFunctionInfo *fi;
if (const auto *fpt = dyn_cast<FunctionProtoType>(ft)) {
- SmallVector<mlir::Type> mlirParamTypes;
- for (unsigned i = 0; i < fpt->getNumParams(); ++i) {
- mlirParamTypes.push_back(convertType(fpt->getParamType(i)));
- }
- return cir::FuncType::get(
- mlirParamTypes, convertType(fpt->getReturnType().getUnqualifiedType()),
- fpt->isVariadic());
+ fi = &arrangeFreeFunctionType(
+ CanQual<FunctionProtoType>::CreateUnsafe(QualType(fpt, 0)));
+ } else {
+ const FunctionNoProtoType *fnpt = cast<FunctionNoProtoType>(ft);
+ fi = &arrangeFreeFunctionType(
+ CanQual<FunctionNoProtoType>::CreateUnsafe(QualType(fnpt, 0)));
}
- cgm.errorNYI(SourceLocation(), "non-prototype function type", qft);
- return cir::FuncType::get(SmallVector<mlir::Type, 1>{}, cgm.VoidTy);
+
+ mlir::Type resultType = getFunctionType(*fi);
+
+ return resultType;
}
// This is CIR's version of CodeGenTypes::addRecordTypeName. It isn't shareable
@@ -494,10 +492,12 @@ bool CIRGenTypes::isZeroInitializable(clang::QualType t) {
}
const CIRGenFunctionInfo &
-CIRGenTypes::arrangeCIRFunctionInfo(CanQualType returnType) {
+CIRGenTypes::arrangeCIRFunctionInfo(CanQualType returnType,
+ llvm::ArrayRef<CanQualType> argTypes,
+ RequiredArgs required) {
// Lookup or create unique function info.
llvm::FoldingSetNodeID id;
- CIRGenFunctionInfo::Profile(id, returnType);
+ CIRGenFunctionInfo::Profile(id, required, returnType, argTypes);
void *insertPos = nullptr;
CIRGenFunctionInfo *fi = functionInfos.FindNodeOrInsertPos(id, insertPos);
@@ -507,14 +507,13 @@ CIRGenTypes::arrangeCIRFunctionInfo(CanQualType returnType) {
assert(!cir::MissingFeatures::opCallCallConv());
// Construction the function info. We co-allocate the ArgInfos.
- fi = CIRGenFunctionInfo::create(returnType);
+ fi = CIRGenFunctionInfo::create(returnType, argTypes, required);
functionInfos.InsertNode(fi, insertPos);
bool inserted = functionsBeingProcessed.insert(fi).second;
(void)inserted;
assert(inserted && "Are functions being processed recursively?");
- assert(!cir::MissingFeatures::opCallCallConv());
getABIInfo().computeInfo(*fi);
// Loop over all of the computed argument and return value info. If any of
@@ -524,7 +523,9 @@ CIRGenTypes::arrangeCIRFunctionInfo(CanQualType returnType) {
if (retInfo.canHaveCoerceToType() && retInfo.getCoerceToType() == nullptr)
retInfo.setCoerceToType(convertType(fi->getReturnType()));
- assert(!cir::MissingFeatures::opCallArgs());
+ for (auto &i : fi->arguments())
+ if (i.info.canHaveCoerceToType() && i.info.getCoerceToType() == nullptr)
+ i.info.setCoerceToType(convertType(i.type));
bool erased = functionsBeingProcessed.erase(fi);
(void)erased;
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.h b/clang/lib/CIR/CodeGen/CIRGenTypes.h
index 5b4027601ca3a..e82bf5197d4a2 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.h
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.h
@@ -123,7 +123,17 @@ class CIRGenTypes {
const CIRGenFunctionInfo &arrangeFreeFunctionCall(const FunctionType *fnType);
- const CIRGenFunctionInfo &arrangeCIRFunctionInfo(CanQualType returnType);
+ const CIRGenFunctionInfo &
+ arrangeCIRFunctionInfo(CanQualType returnType,
+ llvm::ArrayRef<CanQualType> argTypes,
+ RequiredArgs required);
+
+ const CIRGenFunctionInfo &
+ arrangeFreeFunctionType(CanQual<FunctionProtoType> fpt);
+ const CIRGenFunctionInfo &
+ arrangeFreeFunctionType(CanQual<FunctionNoProtoType> fnpt);
+
+ cir::FuncType getFunctionType(const CIRGenFunctionInfo &fi);
};
} // namespace clang::CIRGen
diff --git a/clang/lib/CIR/CodeGen/TargetInfo.cpp b/clang/lib/CIR/CodeGen/TargetInfo.cpp
index 0d0ffb93d4e7e..efba2c2345ff4 100644
--- a/clang/lib/CIR/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CIR/CodeGen/TargetInfo.cpp
@@ -32,8 +32,14 @@ void X8664ABIInfo::computeInfo(CIRGenFunctionInfo &funcInfo) const {
// Top level CIR has unlimited arguments and return types. Lowering for ABI
// specific concerns should happen during a lowering phase. Assume everything
// is direct for now.
- assert(!cir::MissingFeatures::opCallArgs());
-
+ for (CIRGenFunctionInfo::arg_iterator it = funcInfo.arg_begin(),
+ ie = funcInfo.arg_end();
+ it != ie; ++it) {
+ if (testIfIsVoidTy(it->type))
+ it->info = cir::ABIArgInfo::getIgnore();
+ else
+ it->info = cir::ABIArgInfo::getDirect(cgt.convertType(it->type));
+ }
CanQualType retTy = funcInfo.getReturnType();
if (testIfIsVoidTy(retTy))
funcInfo.getReturnInfo() = cir::ABIArgInfo::getIgnore();
diff --git a/clang/test/CIR/CodeGen/basic.c b/clang/test/CIR/CodeGen/basic.c
index 1845d3b64bf68..70dd885f4f6d7 100644
--- a/clang/test/CIR/CodeGen/basic.c
+++ b/clang/test/CIR/CodeGen/basic.c
@@ -233,6 +233,19 @@ int f8(int *p) {
// OGCG: %[[P2:.*]] = load ptr, ptr %[[P_PTR]], align 8
// OGCG: %[[STAR_P:.*]] = load i32, ptr %[[P2]], align 4
+
+void f9() {}
+
+// CIR: cir.func @f9()
+// CIR-NEXT: cir.return
+
+// LLVM: define void @f9()
+// LLVM-NEXT: ret void
+
+// OGCG: define{{.*}} void @f9()
+// OGCG-NEXT: entry:
+// OGCG-NEXT: ret void
+
typedef unsigned long size_type;
typedef unsigned long _Tp;
>From 02b5829537c3861f245df4bfff692ee05f61826d Mon Sep 17 00:00:00 2001
From: Iris Shi <0.0 at owo.li>
Date: Thu, 24 Apr 2025 18:51:22 +0800
Subject: [PATCH 2/2] apply suggestions
---
clang/include/clang/CIR/MissingFeatures.h | 2 +
clang/lib/CIR/CodeGen/CIRGenCall.cpp | 54 ++++++++++++++--------
clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h | 29 ++++++------
clang/lib/CIR/CodeGen/CIRGenModule.cpp | 5 +-
clang/lib/CIR/CodeGen/CIRGenTypes.cpp | 3 +-
clang/lib/CIR/CodeGen/TargetInfo.cpp | 10 ++--
6 files changed, 61 insertions(+), 42 deletions(-)
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index 6bfc1199aea55..c4cc863ff26f7 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -159,6 +159,8 @@ struct MissingFeatures {
static bool bitfields() { return false; }
static bool typeChecks() { return false; }
static bool lambdaFieldToName() { return false; }
+ static bool paramInfo() { return false; }
+ static bool funcTypeExtInfo() { return false; }
// Missing types
static bool dataMemberType() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index b223bc494f928..f1bbfd2c513db 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -25,25 +25,34 @@ CIRGenFunctionInfo::create(CanQualType resultType,
RequiredArgs required) {
void *buffer = operator new(totalSizeToAlloc<ArgInfo>(argTypes.size() + 1));
+ assert(!cir::MissingFeatures::paramInfo());
+ assert(!cir::MissingFeatures::funcTypeExtInfo());
+
CIRGenFunctionInfo *fi = new (buffer) CIRGenFunctionInfo();
fi->required = required;
fi->numArgs = argTypes.size();
- fi->getArgsBuffer()[0].type = resultType;
- for (unsigned i = 0; i < argTypes.size(); ++i)
- fi->getArgsBuffer()[i + 1].type = argTypes[i];
+
+ // ArgsBuffer contains the return type at index 0, and the argument types
+ // starting at index 1, so there are argTypes.size() + 1 elements in total.
+ unsigned idx = 1;
+ ArgInfo *argsBuffer = fi->getArgsBuffer();
+ argsBuffer[0].type = resultType;
+ for (const auto &argType : argTypes)
+ argsBuffer[idx++].type = argType;
return fi;
}
cir::FuncType CIRGenTypes::getFunctionType(const CIRGenFunctionInfo &fi) {
bool inserted = functionsBeingProcessed.insert(&fi).second;
+ (void)inserted;
assert(inserted && "Recursively being processed?");
- mlir::Type resultType = nullptr;
- const cir::ABIArgInfo &retAI = fi.getReturnInfo();
+ mlir::Type resultType;
+ const cir::ABIArgInfo &retInfo = fi.getReturnInfo();
- switch (retAI.getKind()) {
+ switch (retInfo.getKind()) {
case cir::ABIArgInfo::Ignore:
// TODO(CIR): This should probably be the None type from the builtin
// dialect.
@@ -51,31 +60,36 @@ cir::FuncType CIRGenTypes::getFunctionType(const CIRGenFunctionInfo &fi) {
break;
case cir::ABIArgInfo::Direct:
- resultType = retAI.getCoerceToType();
+ resultType = retInfo.getCoerceToType();
break;
default:
- assert(false && "NYI");
+ cgm.errorNYI("getFunctionType: unhandled return kind");
}
- SmallVector<mlir::Type, 8> argTypes;
- unsigned argNo = 0;
- CIRGenFunctionInfo::const_arg_iterator it = fi.arg_begin(),
- ie = it + fi.getNumRequiredArgs();
- for (; it != ie; ++it, ++argNo) {
- const auto &argInfo = it->info;
+ // TODO(cir): ClangToCIRArgMapping
- switch (argInfo.getKind()) {
- default:
- llvm_unreachable("NYI");
- case cir::ABIArgInfo::Direct:
- mlir::Type argType = argInfo.getCoerceToType();
- argTypes.push_back(argType);
+ SmallVector<mlir::Type, 8> argTypes(fi.getNumRequiredArgs());
+
+ unsigned argNo = 0;
+ llvm::ArrayRef<CIRGenFunctionInfoArgInfo> argInfos(fi.argInfoBegin(),
+ fi.getNumRequiredArgs());
+ for (const auto &argInfo : argInfos) {
+ const auto &abiArgInfo = argInfo.info;
+
+ switch (abiArgInfo.getKind()) {
+ case cir::ABIArgInfo::Direct: {
+ mlir::Type argType = abiArgInfo.getCoerceToType();
+ argTypes[argNo++] = argType;
break;
}
+ default:
+ cgm.errorNYI("getFunctionType: unhandled argument kind");
+ }
}
bool erased = functionsBeingProcessed.erase(&fi);
+ (void)erased;
assert(erased && "Not in set?");
return cir::FuncType::get(argTypes,
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h b/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h
index f08fe46ad98a1..05463a1412a5b 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h
@@ -103,7 +103,7 @@ class CIRGenFunctionInfo final
llvm::ArrayRef<CanQualType> argTypes) {
id.AddBoolean(required.getOpaqueData());
resultType.Profile(id);
- for (const auto &arg : argTypes)
+ for (const CanQualType &arg : argTypes)
arg.Profile(id);
}
@@ -111,8 +111,8 @@ class CIRGenFunctionInfo final
void Profile(llvm::FoldingSetNodeID &id) {
id.AddBoolean(required.getOpaqueData());
getReturnType().Profile(id);
- for (const auto &i : arguments())
- i.type.Profile(id);
+ for (const ArgInfo &argInfo : argInfos())
+ argInfo.type.Profile(id);
}
CanQualType getReturnType() const { return getArgsBuffer()[0].type; }
@@ -124,24 +124,27 @@ class CIRGenFunctionInfo final
using const_arg_iterator = const ArgInfo *;
using arg_iterator = ArgInfo *;
- const_arg_iterator arg_begin() const { return getArgsBuffer() + 1; }
- const_arg_iterator arg_end() const { return getArgsBuffer() + 1 + numArgs; }
- arg_iterator arg_begin() { return getArgsBuffer() + 1; }
- arg_iterator arg_end() { return getArgsBuffer() + 1 + numArgs; }
+ const_arg_iterator argInfoBegin() const { return getArgsBuffer() + 1; }
+ const_arg_iterator argInfoEnd() const {
+ return getArgsBuffer() + 1 + numArgs;
+ }
+ arg_iterator argInfoBegin() { return getArgsBuffer() + 1; }
+ arg_iterator argInfoEnd() { return getArgsBuffer() + 1 + numArgs; }
- unsigned arg_size() const { return numArgs; }
+ unsigned argInfoSize() const { return numArgs; }
- llvm::MutableArrayRef<ArgInfo> arguments() {
- return llvm::MutableArrayRef<ArgInfo>(arg_begin(), numArgs);
+ llvm::MutableArrayRef<ArgInfo> argInfos() {
+ return llvm::MutableArrayRef<ArgInfo>(argInfoBegin(), numArgs);
}
- llvm::ArrayRef<ArgInfo> arguments() const {
- return llvm::ArrayRef<ArgInfo>(arg_begin(), numArgs);
+ llvm::ArrayRef<ArgInfo> argInfos() const {
+ return llvm::ArrayRef<ArgInfo>(argInfoBegin(), numArgs);
}
bool isVariadic() const { return required.allowsOptionalArgs(); }
RequiredArgs getRequiredArgs() const { return required; }
unsigned getNumRequiredArgs() const {
- return isVariadic() ? getRequiredArgs().getNumRequiredArgs() : arg_size();
+ return isVariadic() ? getRequiredArgs().getNumRequiredArgs()
+ : argInfoSize();
}
};
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index fad1416fa2225..9b5423c69c94c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -22,6 +22,7 @@
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/MissingFeatures.h"
+#include "CIRGenFunctionInfo.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/Location.h"
#include "mlir/IR/MLIRContext.h"
@@ -222,8 +223,8 @@ void CIRGenModule::emitGlobalFunctionDefinition(clang::GlobalDecl gd,
funcDecl->getType()
->getCanonicalTypeUnqualified()
.getAs<FunctionNoProtoType>()) {
- auto &fi = getTypes().arrangeCIRFunctionInfo(noProto->getReturnType(), {},
- RequiredArgs::All);
+ const CIRGenFunctionInfo &fi = getTypes().arrangeCIRFunctionInfo(
+ noProto->getReturnType(), {}, RequiredArgs::All);
funcType = getTypes().getFunctionType(fi);
} else
funcType = cast<cir::FuncType>(convertType(funcDecl->getType()));
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index bf3d96af37936..e46960ad895bb 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -1,5 +1,6 @@
#include "CIRGenTypes.h"
+#include "CIRGenFunctionInfo.h"
#include "CIRGenModule.h"
#include "clang/AST/ASTContext.h"
@@ -523,7 +524,7 @@ CIRGenTypes::arrangeCIRFunctionInfo(CanQualType returnType,
if (retInfo.canHaveCoerceToType() && retInfo.getCoerceToType() == nullptr)
retInfo.setCoerceToType(convertType(fi->getReturnType()));
- for (auto &i : fi->arguments())
+ for (CIRGenFunctionInfoArgInfo &i : fi->argInfos())
if (i.info.canHaveCoerceToType() && i.info.getCoerceToType() == nullptr)
i.info.setCoerceToType(convertType(i.type));
diff --git a/clang/lib/CIR/CodeGen/TargetInfo.cpp b/clang/lib/CIR/CodeGen/TargetInfo.cpp
index efba2c2345ff4..0eb9debff62a6 100644
--- a/clang/lib/CIR/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CIR/CodeGen/TargetInfo.cpp
@@ -32,13 +32,11 @@ void X8664ABIInfo::computeInfo(CIRGenFunctionInfo &funcInfo) const {
// Top level CIR has unlimited arguments and return types. Lowering for ABI
// specific concerns should happen during a lowering phase. Assume everything
// is direct for now.
- for (CIRGenFunctionInfo::arg_iterator it = funcInfo.arg_begin(),
- ie = funcInfo.arg_end();
- it != ie; ++it) {
- if (testIfIsVoidTy(it->type))
- it->info = cir::ABIArgInfo::getIgnore();
+ for (CIRGenFunctionInfoArgInfo &argInfo : funcInfo.argInfos()) {
+ if (testIfIsVoidTy(argInfo.type))
+ argInfo.info = cir::ABIArgInfo::getIgnore();
else
- it->info = cir::ABIArgInfo::getDirect(cgt.convertType(it->type));
+ argInfo.info = cir::ABIArgInfo::getDirect(cgt.convertType(argInfo.type));
}
CanQualType retTy = funcInfo.getReturnType();
if (testIfIsVoidTy(retTy))
More information about the cfe-commits
mailing list