152 lines
5.2 KiB
C++
152 lines
5.2 KiB
C++
//==-- CIRGenFunctionInfo.h - Representation of fn argument/return types ---==//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Defines CIRGenFunctionInfo and associated types used in representing the
|
|
// CIR source types and ABI-coerced types for function arguments and
|
|
// return values.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_CLANG_CIR_CIRGENFUNCTIONINFO_H
|
|
#define LLVM_CLANG_CIR_CIRGENFUNCTIONINFO_H
|
|
|
|
#include "clang/AST/CanonicalType.h"
|
|
#include "clang/CIR/MissingFeatures.h"
|
|
#include "llvm/ADT/FoldingSet.h"
|
|
#include "llvm/Support/TrailingObjects.h"
|
|
|
|
namespace clang::CIRGen {
|
|
|
|
/// 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
|
|
getFromProtoWithExtraSlots(const clang::FunctionProtoType *prototype,
|
|
unsigned additional) {
|
|
if (!prototype->isVariadic())
|
|
return All;
|
|
|
|
if (prototype->hasExtParameterInfos())
|
|
llvm_unreachable("NYI");
|
|
|
|
return RequiredArgs(prototype->getNumParams() + additional);
|
|
}
|
|
|
|
static RequiredArgs
|
|
getFromProtoWithExtraSlots(clang::CanQual<clang::FunctionProtoType> prototype,
|
|
unsigned additional) {
|
|
return getFromProtoWithExtraSlots(prototype.getTypePtr(), additional);
|
|
}
|
|
|
|
unsigned getNumRequiredArgs() const {
|
|
assert(allowsOptionalArgs());
|
|
return numRequired;
|
|
}
|
|
};
|
|
|
|
// 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<CIRGenFunctionInfo, CanQualType> {
|
|
RequiredArgs required;
|
|
|
|
unsigned numArgs;
|
|
|
|
CanQualType *getArgTypes() { return getTrailingObjects(); }
|
|
const CanQualType *getArgTypes() const { return getTrailingObjects(); }
|
|
|
|
CIRGenFunctionInfo() : required(RequiredArgs::All) {}
|
|
|
|
public:
|
|
static CIRGenFunctionInfo *create(CanQualType resultType,
|
|
llvm::ArrayRef<CanQualType> argTypes,
|
|
RequiredArgs required);
|
|
|
|
void operator delete(void *p) { ::operator delete(p); }
|
|
|
|
// Friending class TrailingObjects is apparantly not good enough for MSVC, so
|
|
// these have to be public.
|
|
friend class TrailingObjects;
|
|
|
|
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)
|
|
static void Profile(llvm::FoldingSetNodeID &id, RequiredArgs required,
|
|
CanQualType resultType,
|
|
llvm::ArrayRef<CanQualType> argTypes) {
|
|
id.AddBoolean(required.getOpaqueData());
|
|
resultType.Profile(id);
|
|
for (const CanQualType &arg : argTypes)
|
|
arg.Profile(id);
|
|
}
|
|
|
|
// NOLINTNEXTLINE(readability-identifier-naming)
|
|
void Profile(llvm::FoldingSetNodeID &id) {
|
|
// 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<CanQualType> arguments() const {
|
|
return llvm::ArrayRef<CanQualType>(argTypesBegin(), numArgs);
|
|
}
|
|
|
|
llvm::ArrayRef<CanQualType> requiredArguments() const {
|
|
return llvm::ArrayRef<CanQualType>(argTypesBegin(), getNumRequiredArgs());
|
|
}
|
|
|
|
CanQualType getReturnType() const { return getArgTypes()[0]; }
|
|
|
|
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 argTypeSize() const { return numArgs; }
|
|
|
|
llvm::MutableArrayRef<CanQualType> argTypes() {
|
|
return llvm::MutableArrayRef<CanQualType>(argTypesBegin(), numArgs);
|
|
}
|
|
llvm::ArrayRef<CanQualType> argTypes() const {
|
|
return llvm::ArrayRef<CanQualType>(argTypesBegin(), numArgs);
|
|
}
|
|
|
|
bool isVariadic() const { return required.allowsOptionalArgs(); }
|
|
RequiredArgs getRequiredArgs() const { return required; }
|
|
unsigned getNumRequiredArgs() const {
|
|
return isVariadic() ? getRequiredArgs().getNumRequiredArgs()
|
|
: argTypeSize();
|
|
}
|
|
};
|
|
|
|
} // namespace clang::CIRGen
|
|
|
|
#endif
|