152 lines · c
1//==-- CIRGenFunctionInfo.h - Representation of fn argument/return types ---==//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// Defines CIRGenFunctionInfo and associated types used in representing the10// CIR source types and ABI-coerced types for function arguments and11// return values.12//13//===----------------------------------------------------------------------===//14 15#ifndef LLVM_CLANG_CIR_CIRGENFUNCTIONINFO_H16#define LLVM_CLANG_CIR_CIRGENFUNCTIONINFO_H17 18#include "clang/AST/CanonicalType.h"19#include "clang/CIR/MissingFeatures.h"20#include "llvm/ADT/FoldingSet.h"21#include "llvm/Support/TrailingObjects.h"22 23namespace clang::CIRGen {24 25/// A class for recording the number of arguments that a function signature26/// requires.27class RequiredArgs {28 /// The number of required arguments, or ~0 if the signature does not permit29 /// optional arguments.30 unsigned numRequired;31 32public:33 enum All_t { All };34 35 RequiredArgs(All_t _) : numRequired(~0U) {}36 explicit RequiredArgs(unsigned n) : numRequired(n) { assert(n != ~0U); }37 38 unsigned getOpaqueData() const { return numRequired; }39 40 bool allowsOptionalArgs() const { return numRequired != ~0U; }41 42 /// Compute the arguments required by the given formal prototype, given that43 /// there may be some additional, non-formal arguments in play.44 ///45 /// If FD is not null, this will consider pass_object_size params in FD.46 static RequiredArgs47 getFromProtoWithExtraSlots(const clang::FunctionProtoType *prototype,48 unsigned additional) {49 if (!prototype->isVariadic())50 return All;51 52 if (prototype->hasExtParameterInfos())53 llvm_unreachable("NYI");54 55 return RequiredArgs(prototype->getNumParams() + additional);56 }57 58 static RequiredArgs59 getFromProtoWithExtraSlots(clang::CanQual<clang::FunctionProtoType> prototype,60 unsigned additional) {61 return getFromProtoWithExtraSlots(prototype.getTypePtr(), additional);62 }63 64 unsigned getNumRequiredArgs() const {65 assert(allowsOptionalArgs());66 return numRequired;67 }68};69 70// The TrailingObjects for this class contain the function return type in the71// first CanQualType slot, followed by the argument types.72class CIRGenFunctionInfo final73 : public llvm::FoldingSetNode,74 private llvm::TrailingObjects<CIRGenFunctionInfo, CanQualType> {75 RequiredArgs required;76 77 unsigned numArgs;78 79 CanQualType *getArgTypes() { return getTrailingObjects(); }80 const CanQualType *getArgTypes() const { return getTrailingObjects(); }81 82 CIRGenFunctionInfo() : required(RequiredArgs::All) {}83 84public:85 static CIRGenFunctionInfo *create(CanQualType resultType,86 llvm::ArrayRef<CanQualType> argTypes,87 RequiredArgs required);88 89 void operator delete(void *p) { ::operator delete(p); }90 91 // Friending class TrailingObjects is apparantly not good enough for MSVC, so92 // these have to be public.93 friend class TrailingObjects;94 95 using const_arg_iterator = const CanQualType *;96 using arg_iterator = CanQualType *;97 98 // This function has to be CamelCase because llvm::FoldingSet requires so.99 // NOLINTNEXTLINE(readability-identifier-naming)100 static void Profile(llvm::FoldingSetNodeID &id, RequiredArgs required,101 CanQualType resultType,102 llvm::ArrayRef<CanQualType> argTypes) {103 id.AddBoolean(required.getOpaqueData());104 resultType.Profile(id);105 for (const CanQualType &arg : argTypes)106 arg.Profile(id);107 }108 109 // NOLINTNEXTLINE(readability-identifier-naming)110 void Profile(llvm::FoldingSetNodeID &id) {111 // If the Profile functions get out of sync, we can end up with incorrect112 // function signatures, so we call the static Profile function here rather113 // than duplicating the logic.114 Profile(id, required, getReturnType(), arguments());115 }116 117 llvm::ArrayRef<CanQualType> arguments() const {118 return llvm::ArrayRef<CanQualType>(argTypesBegin(), numArgs);119 }120 121 llvm::ArrayRef<CanQualType> requiredArguments() const {122 return llvm::ArrayRef<CanQualType>(argTypesBegin(), getNumRequiredArgs());123 }124 125 CanQualType getReturnType() const { return getArgTypes()[0]; }126 127 const_arg_iterator argTypesBegin() const { return getArgTypes() + 1; }128 const_arg_iterator argTypesEnd() const { return getArgTypes() + 1 + numArgs; }129 arg_iterator argTypesBegin() { return getArgTypes() + 1; }130 arg_iterator argTypesEnd() { return getArgTypes() + 1 + numArgs; }131 132 unsigned argTypeSize() const { return numArgs; }133 134 llvm::MutableArrayRef<CanQualType> argTypes() {135 return llvm::MutableArrayRef<CanQualType>(argTypesBegin(), numArgs);136 }137 llvm::ArrayRef<CanQualType> argTypes() const {138 return llvm::ArrayRef<CanQualType>(argTypesBegin(), numArgs);139 }140 141 bool isVariadic() const { return required.allowsOptionalArgs(); }142 RequiredArgs getRequiredArgs() const { return required; }143 unsigned getNumRequiredArgs() const {144 return isVariadic() ? getRequiredArgs().getNumRequiredArgs()145 : argTypeSize();146 }147};148 149} // namespace clang::CIRGen150 151#endif152