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