slang_rs_context.cpp revision 109e90a854ac8d8f4df24ef27db636a641ba9913
1/*
2 * Copyright 2010-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#include "slang_rs_context.h"
18
19#include <string>
20
21#include "clang/AST/ASTContext.h"
22#include "clang/AST/Decl.h"
23#include "clang/AST/DeclBase.h"
24#include "clang/AST/Mangle.h"
25#include "clang/AST/Type.h"
26
27#include "clang/Basic/Linkage.h"
28#include "clang/Basic/TargetInfo.h"
29
30#include "llvm/IR/LLVMContext.h"
31#include "llvm/IR/DataLayout.h"
32
33#include "slang.h"
34#include "slang_assert.h"
35#include "slang_rs_export_foreach.h"
36#include "slang_rs_export_func.h"
37#include "slang_rs_export_type.h"
38#include "slang_rs_export_var.h"
39#include "slang_rs_exportable.h"
40#include "slang_rs_pragma_handler.h"
41#include "slang_rs_reflection.h"
42
43namespace slang {
44
45RSContext::RSContext(clang::Preprocessor &PP,
46                     clang::ASTContext &Ctx,
47                     const clang::TargetInfo &Target,
48                     PragmaList *Pragmas,
49                     unsigned int TargetAPI,
50                     bool Verbose)
51    : mPP(PP),
52      mCtx(Ctx),
53      mPragmas(Pragmas),
54      mTargetAPI(TargetAPI),
55      mVerbose(Verbose),
56      mDataLayout(NULL),
57      mLLVMContext(llvm::getGlobalContext()),
58      mLicenseNote(NULL),
59      mRSPackageName("android.renderscript"),
60      version(0),
61      mMangleCtx(Ctx.createMangleContext()),
62      mIs64Bit(Target.getPointerWidth(0) == 64) {
63
64  AddPragmaHandlers(PP, this);
65
66  // Prepare target data
67  mDataLayout = new llvm::DataLayout(Target.getTargetDescription());
68}
69
70bool RSContext::processExportVar(const clang::VarDecl *VD) {
71  slangAssert(!VD->getName().empty() && "Variable name should not be empty");
72
73  // TODO(zonr): some check on variable
74
75  RSExportType *ET = RSExportType::CreateFromDecl(this, VD);
76  if (!ET)
77    return false;
78
79  RSExportVar *EV = new RSExportVar(this, VD, ET);
80  if (EV == NULL)
81    return false;
82  else
83    mExportVars.push_back(EV);
84
85  return true;
86}
87
88bool RSContext::processExportFunc(const clang::FunctionDecl *FD) {
89  slangAssert(!FD->getName().empty() && "Function name should not be empty");
90
91  if (!FD->isThisDeclarationADefinition()) {
92    return true;
93  }
94
95  if (FD->getStorageClass() != clang::SC_None) {
96    fprintf(stderr, "RSContext::processExportFunc : cannot export extern or "
97                    "static function '%s'\n", FD->getName().str().c_str());
98    return false;
99  }
100
101  if (RSExportForEach::isSpecialRSFunc(mTargetAPI, FD)) {
102    // Do not reflect specialized functions like init, dtor, or graphics root.
103    return RSExportForEach::validateSpecialFuncDecl(mTargetAPI, this, FD);
104  } else if (RSExportForEach::isRSForEachFunc(mTargetAPI, this, FD)) {
105    RSExportForEach *EFE = RSExportForEach::Create(this, FD);
106    if (EFE == NULL)
107      return false;
108    else
109      mExportForEach.push_back(EFE);
110    return true;
111  }
112
113  RSExportFunc *EF = RSExportFunc::Create(this, FD);
114  if (EF == NULL)
115    return false;
116  else
117    mExportFuncs.push_back(EF);
118
119  return true;
120}
121
122
123bool RSContext::processExportType(const llvm::StringRef &Name) {
124  clang::TranslationUnitDecl *TUDecl = mCtx.getTranslationUnitDecl();
125
126  slangAssert(TUDecl != NULL && "Translation unit declaration (top-level "
127                                "declaration) is null object");
128
129  const clang::IdentifierInfo *II = mPP.getIdentifierInfo(Name);
130  if (II == NULL)
131    // TODO(zonr): alert identifier @Name mark as an exportable type cannot be
132    //             found
133    return false;
134
135  clang::DeclContext::lookup_const_result R = TUDecl->lookup(II);
136  RSExportType *ET = NULL;
137
138  for (clang::DeclContext::lookup_const_iterator I = R.begin(), E = R.end();
139       I != E;
140       I++) {
141    clang::NamedDecl *const ND = *I;
142    const clang::Type *T = NULL;
143
144    switch (ND->getKind()) {
145      case clang::Decl::Typedef: {
146        T = static_cast<const clang::TypedefDecl*>(
147            ND)->getCanonicalDecl()->getUnderlyingType().getTypePtr();
148        break;
149      }
150      case clang::Decl::Record: {
151        T = static_cast<const clang::RecordDecl*>(ND)->getTypeForDecl();
152        break;
153      }
154      default: {
155        // unsupported, skip
156        break;
157      }
158    }
159
160    if (T != NULL)
161      ET = RSExportType::Create(this, T);
162  }
163
164  return (ET != NULL);
165}
166
167
168// Possibly re-order ForEach exports (maybe generating a dummy "root" function).
169// We require "root" to be listed as slot 0 of our exported compute kernels,
170// so this only needs to be created if we have other non-root kernels.
171void RSContext::cleanupForEach() {
172  bool foundNonRoot = false;
173  ExportForEachList::iterator begin = mExportForEach.begin();
174
175  for (ExportForEachList::iterator I = begin, E = mExportForEach.end();
176       I != E;
177       I++) {
178    RSExportForEach *EFE = *I;
179    if (!EFE->getName().compare("root")) {
180      if (I == begin) {
181        // Nothing to do, since it is the first function
182        return;
183      }
184
185      mExportForEach.erase(I);
186      mExportForEach.push_front(EFE);
187      return;
188    } else {
189      foundNonRoot = true;
190    }
191  }
192
193  // If we found a non-root kernel, but no root() function, we need to add a
194  // dummy version (so that script->script calls of rsForEach don't behave
195  // erratically).
196  if (foundNonRoot) {
197    RSExportForEach *DummyRoot = RSExportForEach::CreateDummyRoot(this);
198    mExportForEach.push_front(DummyRoot);
199  }
200}
201
202
203bool RSContext::processExport() {
204  bool valid = true;
205
206  if (getDiagnostics()->hasErrorOccurred()) {
207    return false;
208  }
209
210  // Export variable
211  clang::TranslationUnitDecl *TUDecl = mCtx.getTranslationUnitDecl();
212  for (clang::DeclContext::decl_iterator DI = TUDecl->decls_begin(),
213           DE = TUDecl->decls_end();
214       DI != DE;
215       DI++) {
216    if (DI->getKind() == clang::Decl::Var) {
217      clang::VarDecl *VD = (clang::VarDecl*) (*DI);
218      if (VD->getFormalLinkage() == clang::ExternalLinkage) {
219        if (!processExportVar(VD)) {
220          valid = false;
221        }
222      }
223    } else if (DI->getKind() == clang::Decl::Function) {
224      // Export functions
225      clang::FunctionDecl *FD = (clang::FunctionDecl*) (*DI);
226      if (FD->getFormalLinkage() == clang::ExternalLinkage) {
227        if (!processExportFunc(FD)) {
228          valid = false;
229        }
230      }
231    }
232  }
233
234  if (valid) {
235    cleanupForEach();
236  }
237
238  // Finally, export type forcely set to be exported by user
239  for (NeedExportTypeSet::const_iterator EI = mNeedExportTypes.begin(),
240           EE = mNeedExportTypes.end();
241       EI != EE;
242       EI++) {
243    if (!processExportType(EI->getKey())) {
244      valid = false;
245    }
246  }
247
248  return valid;
249}
250
251bool RSContext::insertExportType(const llvm::StringRef &TypeName,
252                                 RSExportType *ET) {
253  ExportTypeMap::value_type *NewItem =
254      ExportTypeMap::value_type::Create(TypeName.begin(),
255                                        TypeName.end(),
256                                        mExportTypes.getAllocator(),
257                                        ET);
258
259  if (mExportTypes.insert(NewItem)) {
260    return true;
261  } else {
262    free(NewItem);
263    return false;
264  }
265}
266
267RSContext::~RSContext() {
268  delete mLicenseNote;
269  delete mDataLayout;
270  for (ExportableList::iterator I = mExportables.begin(),
271          E = mExportables.end();
272       I != E;
273       I++) {
274    if (!(*I)->isKeep())
275      delete *I;
276  }
277}
278
279}  // namespace slang
280