xref: /freebsd/contrib/llvm-project/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Defines CIRGenFunctionInfo and associated types used in representing the
10 // CIR source types and ABI-coerced types for function arguments and
11 // return values.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_CLANG_CIR_CIRGENFUNCTIONINFO_H
16 #define LLVM_CLANG_CIR_CIRGENFUNCTIONINFO_H
17 
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 
23 namespace clang::CIRGen {
24 
25 /// A class for recording the number of arguments that a function signature
26 /// requires.
27 class RequiredArgs {
28   /// The number of required arguments, or ~0 if the signature does not permit
29   /// optional arguments.
30   unsigned numRequired;
31 
32 public:
33   enum All_t { All };
34 
RequiredArgs(All_t _)35   RequiredArgs(All_t _) : numRequired(~0U) {}
RequiredArgs(unsigned n)36   explicit RequiredArgs(unsigned n) : numRequired(n) { assert(n != ~0U); }
37 
getOpaqueData()38   unsigned getOpaqueData() const { return numRequired; }
39 
allowsOptionalArgs()40   bool allowsOptionalArgs() const { return numRequired != ~0U; }
41 
42   /// Compute the arguments required by the given formal prototype, given that
43   /// 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 RequiredArgs
getFromProtoWithExtraSlots(const clang::FunctionProtoType * prototype,unsigned additional)47   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 RequiredArgs
getFromProtoWithExtraSlots(clang::CanQual<clang::FunctionProtoType> prototype,unsigned additional)59   getFromProtoWithExtraSlots(clang::CanQual<clang::FunctionProtoType> prototype,
60                              unsigned additional) {
61     return getFromProtoWithExtraSlots(prototype.getTypePtr(), additional);
62   }
63 
getNumRequiredArgs()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 the
71 // first CanQualType slot, followed by the argument types.
72 class CIRGenFunctionInfo final
73     : public llvm::FoldingSetNode,
74       private llvm::TrailingObjects<CIRGenFunctionInfo, CanQualType> {
75   RequiredArgs required;
76 
77   unsigned numArgs;
78 
getArgTypes()79   CanQualType *getArgTypes() { return getTrailingObjects(); }
getArgTypes()80   const CanQualType *getArgTypes() const { return getTrailingObjects(); }
81 
CIRGenFunctionInfo()82   CIRGenFunctionInfo() : required(RequiredArgs::All) {}
83 
84 public:
85   static CIRGenFunctionInfo *create(CanQualType resultType,
86                                     llvm::ArrayRef<CanQualType> argTypes,
87                                     RequiredArgs required);
88 
delete(void * p)89   void operator delete(void *p) { ::operator delete(p); }
90 
91   // Friending class TrailingObjects is apparantly not good enough for MSVC, so
92   // 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)
Profile(llvm::FoldingSetNodeID & id,RequiredArgs required,CanQualType resultType,llvm::ArrayRef<CanQualType> argTypes)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)
Profile(llvm::FoldingSetNodeID & id)110   void Profile(llvm::FoldingSetNodeID &id) {
111     // If the Profile functions get out of sync, we can end up with incorrect
112     // function signatures, so we call the static Profile function here rather
113     // than duplicating the logic.
114     Profile(id, required, getReturnType(), arguments());
115   }
116 
arguments()117   llvm::ArrayRef<CanQualType> arguments() const {
118     return llvm::ArrayRef<CanQualType>(argTypesBegin(), numArgs);
119   }
120 
requiredArguments()121   llvm::ArrayRef<CanQualType> requiredArguments() const {
122     return llvm::ArrayRef<CanQualType>(argTypesBegin(), getNumRequiredArgs());
123   }
124 
getReturnType()125   CanQualType getReturnType() const { return getArgTypes()[0]; }
126 
argTypesBegin()127   const_arg_iterator argTypesBegin() const { return getArgTypes() + 1; }
argTypesEnd()128   const_arg_iterator argTypesEnd() const { return getArgTypes() + 1 + numArgs; }
argTypesBegin()129   arg_iterator argTypesBegin() { return getArgTypes() + 1; }
argTypesEnd()130   arg_iterator argTypesEnd() { return getArgTypes() + 1 + numArgs; }
131 
argTypeSize()132   unsigned argTypeSize() const { return numArgs; }
133 
argTypes()134   llvm::MutableArrayRef<CanQualType> argTypes() {
135     return llvm::MutableArrayRef<CanQualType>(argTypesBegin(), numArgs);
136   }
argTypes()137   llvm::ArrayRef<CanQualType> argTypes() const {
138     return llvm::ArrayRef<CanQualType>(argTypesBegin(), numArgs);
139   }
140 
isVariadic()141   bool isVariadic() const { return required.allowsOptionalArgs(); }
getRequiredArgs()142   RequiredArgs getRequiredArgs() const { return required; }
getNumRequiredArgs()143   unsigned getNumRequiredArgs() const {
144     return isVariadic() ? getRequiredArgs().getNumRequiredArgs()
145                         : argTypeSize();
146   }
147 };
148 
149 } // namespace clang::CIRGen
150 
151 #endif
152