diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp index 17bfa19f9fd63..f63b971ac26b4 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp @@ -23,8 +23,9 @@ CIRGenFunctionInfo * CIRGenFunctionInfo::create(CanQualType resultType, llvm::ArrayRef argTypes, RequiredArgs required) { - // The first slot allocated for ArgInfo is for the return value. - void *buffer = operator new(totalSizeToAlloc(argTypes.size() + 1)); + // The first slot allocated for arg type slot is for the return value. + void *buffer = operator new( + totalSizeToAlloc(argTypes.size() + 1)); assert(!cir::MissingFeatures::opCallCIRGenFuncInfoParamInfo()); @@ -33,10 +34,8 @@ CIRGenFunctionInfo::create(CanQualType resultType, fi->required = required; fi->numArgs = argTypes.size(); - ArgInfo *argsBuffer = fi->getArgsBuffer(); - (argsBuffer++)->type = resultType; - for (CanQualType ty : argTypes) - (argsBuffer++)->type = ty; + fi->getArgTypes()[0] = resultType; + std::copy(argTypes.begin(), argTypes.end(), fi->argTypesBegin()); assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo()); return fi; @@ -47,8 +46,8 @@ cir::FuncType CIRGenTypes::getFunctionType(const CIRGenFunctionInfo &fi) { SmallVector argTypes; argTypes.reserve(fi.getNumRequiredArgs()); - for (const CIRGenFunctionInfoArgInfo &argInfo : fi.requiredArguments()) - argTypes.push_back(convertType(argInfo.type)); + for (const CanQualType &argType : fi.requiredArguments()) + argTypes.push_back(convertType(argType)); return cir::FuncType::get(argTypes, (resultType ? resultType : builder.getVoidTy()), @@ -189,13 +188,13 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo, assert(!cir::MissingFeatures::emitLifetimeMarkers()); // Translate all of the arguments as necessary to match the CIR lowering. - for (auto [argNo, arg, argInfo] : - llvm::enumerate(args, funcInfo.argInfos())) { + for (auto [argNo, arg, canQualArgType] : + llvm::enumerate(args, funcInfo.argTypes())) { // Insert a padding argument to ensure proper alignment. assert(!cir::MissingFeatures::opCallPaddingArgs()); - mlir::Type argType = convertType(argInfo.type); + mlir::Type argType = convertType(canQualArgType); if (!mlir::isa(argType)) { mlir::Value v; if (arg.isAggregate()) diff --git a/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h b/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h index b74460b09a44e..12a0a675ce163 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h @@ -21,10 +21,6 @@ namespace clang::CIRGen { -struct CIRGenFunctionInfoArgInfo { - CanQualType type; -}; - /// A class for recording the number of arguments that a function signature /// requires. class RequiredArgs { @@ -70,18 +66,19 @@ class RequiredArgs { } }; +// The TrailingObjects for this class contain the function return type in the +// first CanQualType slot, followed by the argument types. class CIRGenFunctionInfo final : public llvm::FoldingSetNode, - private llvm::TrailingObjects { - using ArgInfo = CIRGenFunctionInfoArgInfo; - + private llvm::TrailingObjects { RequiredArgs required; unsigned numArgs; - ArgInfo *getArgsBuffer() { return getTrailingObjects(); } - const ArgInfo *getArgsBuffer() const { return getTrailingObjects(); } + CanQualType *getArgTypes() { return getTrailingObjects(); } + const CanQualType *getArgTypes() const { + return getTrailingObjects(); + } CIRGenFunctionInfo() : required(RequiredArgs::All) {} @@ -96,8 +93,8 @@ class CIRGenFunctionInfo final // these have to be public. friend class TrailingObjects; - using const_arg_iterator = const ArgInfo *; - using arg_iterator = ArgInfo *; + using const_arg_iterator = const CanQualType *; + using arg_iterator = CanQualType *; // This function has to be CamelCase because llvm::FoldingSet requires so. // NOLINTNEXTLINE(readability-identifier-naming) @@ -112,49 +109,41 @@ class CIRGenFunctionInfo final // NOLINTNEXTLINE(readability-identifier-naming) void Profile(llvm::FoldingSetNodeID &id) { - // It's unfortunate that we are looping over the arguments twice (here and - // in the static Profile function we call from here), but if the Profile - // functions get out of sync, we can end up with incorrect function - // signatures, and we don't have the argument types in the format that the - // static Profile function requires. - llvm::SmallVector argTypes; - for (const ArgInfo &argInfo : arguments()) - argTypes.push_back(argInfo.type); - - Profile(id, required, getReturnType(), argTypes); + // If the Profile functions get out of sync, we can end up with incorrect + // function signatures, so we call the static Profile function here rather + // than duplicating the logic. + Profile(id, required, getReturnType(), arguments()); } - llvm::ArrayRef arguments() const { - return llvm::ArrayRef(argInfoBegin(), numArgs); + llvm::ArrayRef arguments() const { + return llvm::ArrayRef(argTypesBegin(), numArgs); } - llvm::ArrayRef requiredArguments() const { - return llvm::ArrayRef(argInfoBegin(), getNumRequiredArgs()); + llvm::ArrayRef requiredArguments() const { + return llvm::ArrayRef(argTypesBegin(), getNumRequiredArgs()); } - CanQualType getReturnType() const { return getArgsBuffer()[0].type; } + CanQualType getReturnType() const { return getArgTypes()[0]; } - 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; } + const_arg_iterator argTypesBegin() const { return getArgTypes() + 1; } + const_arg_iterator argTypesEnd() const { return getArgTypes() + 1 + numArgs; } + arg_iterator argTypesBegin() { return getArgTypes() + 1; } + arg_iterator argTypesEnd() { return getArgTypes() + 1 + numArgs; } - unsigned argInfoSize() const { return numArgs; } + unsigned argTypeSize() const { return numArgs; } - llvm::MutableArrayRef argInfos() { - return llvm::MutableArrayRef(argInfoBegin(), numArgs); + llvm::MutableArrayRef argTypes() { + return llvm::MutableArrayRef(argTypesBegin(), numArgs); } - llvm::ArrayRef argInfos() const { - return llvm::ArrayRef(argInfoBegin(), numArgs); + llvm::ArrayRef argTypes() const { + return llvm::ArrayRef(argTypesBegin(), numArgs); } bool isVariadic() const { return required.allowsOptionalArgs(); } RequiredArgs getRequiredArgs() const { return required; } unsigned getNumRequiredArgs() const { return isVariadic() ? getRequiredArgs().getNumRequiredArgs() - : argInfoSize(); + : argTypeSize(); } }; diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp index dc8872122995c..45990f198d227 100644 --- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp @@ -542,8 +542,15 @@ CIRGenTypes::arrangeCIRFunctionInfo(CanQualType returnType, void *insertPos = nullptr; CIRGenFunctionInfo *fi = functionInfos.FindNodeOrInsertPos(id, insertPos); - if (fi) + if (fi) { + // We found a matching function info based on id. These asserts verify that + // it really is a match. + assert( + fi->getReturnType() == returnType && + std::equal(fi->argTypesBegin(), fi->argTypesEnd(), argTypes.begin()) && + "Bad match based on CIRGenFunctionInfo folding set id"); return *fi; + } assert(!cir::MissingFeatures::opCallCallConv());