1 /*
2  * Copyright 2011-2012, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_EXPORT_FOREACH_H_  // NOLINT
18 #define _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_EXPORT_FOREACH_H_
19 
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/ADT/SmallVector.h"
22 #include "llvm/Support/raw_ostream.h"
23 
24 #include "clang/AST/Decl.h"
25 
26 #include "slang_assert.h"
27 #include "slang_rs_context.h"
28 #include "slang_rs_exportable.h"
29 #include "slang_rs_export_type.h"
30 
31 namespace clang {
32   class FunctionDecl;
33 }  // namespace clang
34 
35 namespace slang {
36 
37 // Base class for reflecting control-side forEach
38 class RSExportForEach : public RSExportable {
39  public:
40 
41   typedef llvm::SmallVectorImpl<const clang::ParmVarDecl*> InVec;
42   typedef llvm::SmallVectorImpl<const RSExportType*> InTypeVec;
43 
44   typedef InVec::const_iterator InIter;
45   typedef InTypeVec::const_iterator InTypeIter;
46 
47  private:
48   std::string mName;
49 
50   // For diagnostic purposes, we record the order in which we parse
51   // foreach kernels.  Does not apply to a placeholder root.
52   unsigned mOrdinal;
53 
54   RSExportRecordType *mParamPacketType;
55   llvm::SmallVector<const RSExportType*, 16> mInTypes;
56   RSExportType *mOutType;
57   size_t numParams;
58 
59   unsigned int mSignatureMetadata;
60 
61   llvm::SmallVector<const clang::ParmVarDecl*, 16> mIns;
62   const clang::ParmVarDecl *mOut;
63   const clang::ParmVarDecl *mUsrData;
64 
65   // Accumulator for metadata bits corresponding to special parameters.
66   unsigned int mSpecialParameterSignatureMetadata;
67 
68   clang::QualType mResultType;  // return type (if present).
69   bool mHasReturnType;  // does this kernel have a return type?
70   bool mIsKernelStyle;  // is this a pass-by-value kernel?
71 
72   bool mDummyRoot;
73 
74   // TODO(all): Add support for LOD/face when we have them
RSExportForEach(RSContext * Context,const llvm::StringRef & Name,clang::SourceLocation Loc)75   RSExportForEach(RSContext *Context, const llvm::StringRef &Name, clang::SourceLocation Loc)
76     : RSExportable(Context, RSExportable::EX_FOREACH, Loc),
77       mName(Name.data(), Name.size()), mOrdinal(~unsigned(0)),
78       mParamPacketType(nullptr),
79       mOutType(nullptr), numParams(0), mSignatureMetadata(0),
80       mOut(nullptr), mUsrData(nullptr), mSpecialParameterSignatureMetadata(0),
81       mResultType(clang::QualType()), mHasReturnType(false),
82       mIsKernelStyle(false), mDummyRoot(false) {
83   }
84 
85   bool validateAndConstructParams(RSContext *Context,
86                                   const clang::FunctionDecl *FD);
87 
88   bool validateAndConstructOldStyleParams(RSContext *Context,
89                                           const clang::FunctionDecl *FD);
90 
91   bool validateAndConstructKernelParams(RSContext *Context,
92                                         const clang::FunctionDecl *FD);
93 
94   bool processSpecialParameters(RSContext *Context,
95                                 const clang::FunctionDecl *FD,
96                                 size_t *IndexOfFirstSpecialParameter);
97 
98   bool setSignatureMetadata(RSContext *Context,
99                             const clang::FunctionDecl *FD);
100  public:
101   static RSExportForEach *Create(RSContext *Context,
102                                  const clang::FunctionDecl *FD);
103 
104   static RSExportForEach *CreateDummyRoot(RSContext *Context);
105 
getName()106   inline const std::string &getName() const {
107     return mName;
108   }
109 
getOrdinal()110   inline unsigned getOrdinal() const {
111     slangAssert(!mDummyRoot);
112     return mOrdinal;
113   }
114 
getNumParameters()115   inline size_t getNumParameters() const {
116     return numParams;
117   }
118 
hasIns()119   inline bool hasIns() const {
120     return (!mIns.empty());
121   }
122 
hasOut()123   inline bool hasOut() const {
124     return (mOut != nullptr);
125   }
126 
hasUsrData()127   inline bool hasUsrData() const {
128     return (mUsrData != nullptr);
129   }
130 
hasReturn()131   inline bool hasReturn() const {
132     return mHasReturnType;
133   }
134 
getIns()135   inline const InVec& getIns() const {
136     return mIns;
137   }
138 
getInTypes()139   inline const InTypeVec& getInTypes() const {
140     return mInTypes;
141   }
142 
getOutType()143   inline const RSExportType *getOutType() const {
144     return mOutType;
145   }
146 
getParamPacketType()147   inline const RSExportRecordType *getParamPacketType() const {
148     return mParamPacketType;
149   }
150 
getSignatureMetadata()151   inline unsigned int getSignatureMetadata() const {
152     return mSignatureMetadata;
153   }
154 
isDummyRoot()155   inline bool isDummyRoot() const {
156     return mDummyRoot;
157   }
158 
159   // is this a pass-by-value kernel?
isKernelStyle()160   inline bool isKernelStyle() const {
161     return mIsKernelStyle;
162   }
163 
164   typedef RSExportRecordType::const_field_iterator const_param_iterator;
165 
params_begin()166   inline const_param_iterator params_begin() const {
167     slangAssert((mParamPacketType != nullptr) &&
168                 "Get parameter from export foreach having no parameter!");
169     return mParamPacketType->fields_begin();
170   }
171 
params_end()172   inline const_param_iterator params_end() const {
173     slangAssert((mParamPacketType != nullptr) &&
174                 "Get parameter from export foreach having no parameter!");
175     return mParamPacketType->fields_end();
176   }
params_count()177   inline size_t params_count() const {
178     return (mParamPacketType ? mParamPacketType->fields_size() : 0);
179   }
180 
181   static bool isRSForEachFunc(unsigned int targetAPI,
182                               const clang::FunctionDecl *FD);
183 
184   static unsigned getNumInputs(unsigned int targetAPI,
185                               const clang::FunctionDecl *FD);
186 };  // RSExportForEach
187 
188 }  // namespace slang
189 
190 #endif  // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_EXPORT_FOREACH_H_  NOLINT
191