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
31namespace clang {
32  class FunctionDecl;
33}  // namespace clang
34
35namespace slang {
36
37// Base class for reflecting control-side forEach (currently for root()
38// functions that fit appropriate criteria)
39class RSExportForEach : public RSExportable {
40 public:
41
42  typedef llvm::SmallVectorImpl<const clang::ParmVarDecl*> InVec;
43  typedef llvm::SmallVectorImpl<const RSExportType*> InTypeVec;
44
45  typedef InVec::const_iterator InIter;
46  typedef InTypeVec::const_iterator InTypeIter;
47
48 private:
49  std::string mName;
50  RSExportRecordType *mParamPacketType;
51  llvm::SmallVector<const RSExportType*, 16> mInTypes;
52  RSExportType *mOutType;
53  size_t numParams;
54
55  unsigned int mSignatureMetadata;
56
57  llvm::SmallVector<const clang::ParmVarDecl*, 16> mIns;
58  const clang::ParmVarDecl *mOut;
59  const clang::ParmVarDecl *mUsrData;
60  const clang::ParmVarDecl *mX;
61  const clang::ParmVarDecl *mY;
62
63  clang::QualType mResultType;  // return type (if present).
64  bool mHasReturnType;  // does this kernel have a return type?
65  bool mIsKernelStyle;  // is this a pass-by-value kernel?
66
67  bool mDummyRoot;
68
69  // TODO(all): Add support for LOD/face when we have them
70  RSExportForEach(RSContext *Context, const llvm::StringRef &Name)
71    : RSExportable(Context, RSExportable::EX_FOREACH),
72      mName(Name.data(), Name.size()), mParamPacketType(NULL),
73      mOutType(NULL), numParams(0), mSignatureMetadata(0),
74      mOut(NULL), mUsrData(NULL), mX(NULL), mY(NULL),
75      mResultType(clang::QualType()), mHasReturnType(false),
76      mIsKernelStyle(false), mDummyRoot(false) {
77  }
78
79  bool validateAndConstructParams(RSContext *Context,
80                                  const clang::FunctionDecl *FD);
81
82  bool validateAndConstructOldStyleParams(RSContext *Context,
83                                          const clang::FunctionDecl *FD);
84
85  bool validateAndConstructKernelParams(RSContext *Context,
86                                        const clang::FunctionDecl *FD);
87
88  bool validateIterationParameters(RSContext *Context,
89                                   const clang::FunctionDecl *FD,
90                                   size_t *IndexOfFirstIterator);
91
92  bool setSignatureMetadata(RSContext *Context,
93                            const clang::FunctionDecl *FD);
94 public:
95  static RSExportForEach *Create(RSContext *Context,
96                                 const clang::FunctionDecl *FD);
97
98  static RSExportForEach *CreateDummyRoot(RSContext *Context);
99
100  inline const std::string &getName() const {
101    return mName;
102  }
103
104  inline size_t getNumParameters() const {
105    return numParams;
106  }
107
108  inline bool hasIns() const {
109    return (!mIns.empty());
110  }
111
112  inline bool hasOut() const {
113    return (mOut != NULL);
114  }
115
116  inline bool hasUsrData() const {
117    return (mUsrData != NULL);
118  }
119
120  inline bool hasReturn() const {
121    return mHasReturnType;
122  }
123
124  inline const InVec& getIns() const {
125    return mIns;
126  }
127
128  inline const InTypeVec& getInTypes() const {
129    return mInTypes;
130  }
131
132  inline const RSExportType *getOutType() const {
133    return mOutType;
134  }
135
136  inline const RSExportRecordType *getParamPacketType() const {
137    return mParamPacketType;
138  }
139
140  inline unsigned int getSignatureMetadata() const {
141    return mSignatureMetadata;
142  }
143
144  inline bool isDummyRoot() const {
145    return mDummyRoot;
146  }
147
148  typedef RSExportRecordType::const_field_iterator const_param_iterator;
149
150  inline const_param_iterator params_begin() const {
151    slangAssert((mParamPacketType != NULL) &&
152                "Get parameter from export foreach having no parameter!");
153    return mParamPacketType->fields_begin();
154  }
155
156  inline const_param_iterator params_end() const {
157    slangAssert((mParamPacketType != NULL) &&
158                "Get parameter from export foreach having no parameter!");
159    return mParamPacketType->fields_end();
160  }
161
162  inline static bool isInitRSFunc(const clang::FunctionDecl *FD) {
163    if (!FD) {
164      return false;
165    }
166    const llvm::StringRef Name = FD->getName();
167    static llvm::StringRef FuncInit("init");
168    return Name.equals(FuncInit);
169  }
170
171  inline static bool isRootRSFunc(const clang::FunctionDecl *FD) {
172    if (!FD) {
173      return false;
174    }
175    const llvm::StringRef Name = FD->getName();
176    static llvm::StringRef FuncRoot("root");
177    return Name.equals(FuncRoot);
178  }
179
180  inline static bool isDtorRSFunc(const clang::FunctionDecl *FD) {
181    if (!FD) {
182      return false;
183    }
184    const llvm::StringRef Name = FD->getName();
185    static llvm::StringRef FuncDtor(".rs.dtor");
186    return Name.equals(FuncDtor);
187  }
188
189  static bool isGraphicsRootRSFunc(unsigned int targetAPI,
190                                   const clang::FunctionDecl *FD);
191
192  static bool isRSForEachFunc(unsigned int targetAPI, slang::RSContext *Context,
193                              const clang::FunctionDecl *FD);
194
195  inline static bool isSpecialRSFunc(unsigned int targetAPI,
196                                     const clang::FunctionDecl *FD) {
197    return isGraphicsRootRSFunc(targetAPI, FD) || isInitRSFunc(FD) ||
198           isDtorRSFunc(FD);
199  }
200
201  static bool validateSpecialFuncDecl(unsigned int targetAPI,
202                                      slang::RSContext *Context,
203                                      const clang::FunctionDecl *FD);
204};  // RSExportForEach
205
206}  // namespace slang
207
208#endif  // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_EXPORT_FOREACH_H_  NOLINT
209