blob: 53962e7cc911c00b87467b05a5395bf85ec23bd5 [file] [log] [blame]
Zonr Changc383a502010-10-12 01:52:08 +08001/*
Stephen Hines9999ec32012-02-10 18:22:14 -08002 * Copyright 2010-2012, The Android Open Source Project
Zonr Changc383a502010-10-12 01:52:08 +08003 *
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
zonr6315f762010-10-05 15:35:14 +080017#include "slang_rs_context.h"
18
Stephen Hinese639eb52010-11-08 19:27:20 -080019#include <string>
20
21#include "clang/AST/ASTContext.h"
22#include "clang/AST/Decl.h"
23#include "clang/AST/DeclBase.h"
Loganbe274822011-02-16 22:02:54 +080024#include "clang/AST/Mangle.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080025#include "clang/AST/Type.h"
26
27#include "clang/Basic/Linkage.h"
28#include "clang/Basic/TargetInfo.h"
29
zonr6315f762010-10-05 15:35:14 +080030#include "llvm/LLVMContext.h"
31#include "llvm/Target/TargetData.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070032
zonr6315f762010-10-05 15:35:14 +080033#include "slang.h"
Stephen Hines6e6578a2011-02-07 18:05:48 -080034#include "slang_assert.h"
Stephen Hines593a8942011-05-10 15:29:50 -070035#include "slang_rs_export_foreach.h"
zonr6315f762010-10-05 15:35:14 +080036#include "slang_rs_export_func.h"
37#include "slang_rs_export_type.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080038#include "slang_rs_export_var.h"
39#include "slang_rs_exportable.h"
zonr6315f762010-10-05 15:35:14 +080040#include "slang_rs_pragma_handler.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080041#include "slang_rs_reflection.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070042
Stephen Hinese639eb52010-11-08 19:27:20 -080043namespace slang {
Shih-wei Liao462aefd2010-06-04 15:32:04 -070044
Stephen Hines9e5b5032010-11-03 13:19:14 -070045RSContext::RSContext(clang::Preprocessor &PP,
46 clang::ASTContext &Ctx,
Stephen Hines3fd0a942011-01-18 12:27:39 -080047 const clang::TargetInfo &Target,
Stephen Hines4cc67fc2011-01-31 16:48:57 -080048 PragmaList *Pragmas,
Stephen Hines4a4bf922011-08-18 17:20:33 -070049 unsigned int TargetAPI,
Stephen Hines4cc67fc2011-01-31 16:48:57 -080050 std::vector<std::string> *GeneratedFileNames)
zonr6315f762010-10-05 15:35:14 +080051 : mPP(PP),
52 mCtx(Ctx),
53 mTarget(Target),
Stephen Hines3fd0a942011-01-18 12:27:39 -080054 mPragmas(Pragmas),
Stephen Hines4a4bf922011-08-18 17:20:33 -070055 mTargetAPI(TargetAPI),
Stephen Hines4cc67fc2011-01-31 16:48:57 -080056 mGeneratedFileNames(GeneratedFileNames),
zonr6315f762010-10-05 15:35:14 +080057 mTargetData(NULL),
58 mLLVMContext(llvm::getGlobalContext()),
Stephen Hines96ab06c2011-01-05 15:29:26 -080059 mLicenseNote(NULL),
Shih-wei Liao3fa286b2011-02-10 11:04:44 -080060 version(0),
Loganbe274822011-02-16 22:02:54 +080061 mMangleCtx(Ctx.createMangleContext()) {
Stephen Hines6e6578a2011-02-07 18:05:48 -080062 slangAssert(mGeneratedFileNames && "Must supply GeneratedFileNames");
Stephen Hines4cc67fc2011-01-31 16:48:57 -080063
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070064 // For #pragma rs export_type
Stephen Hines9e5b5032010-11-03 13:19:14 -070065 PP.AddPragmaHandler(
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070066 "rs", RSPragmaHandler::CreatePragmaExportTypeHandler(this));
Victor Hsiehd8a0d182010-07-07 19:22:33 +080067
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070068 // For #pragma rs java_package_name
Stephen Hines9e5b5032010-11-03 13:19:14 -070069 PP.AddPragmaHandler(
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070070 "rs", RSPragmaHandler::CreatePragmaJavaPackageNameHandler(this));
Shih-wei Liao462aefd2010-06-04 15:32:04 -070071
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070072 // For #pragma rs set_reflect_license
Stephen Hines9e5b5032010-11-03 13:19:14 -070073 PP.AddPragmaHandler(
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070074 "rs", RSPragmaHandler::CreatePragmaReflectLicenseHandler(this));
75
Stephen Hines96ab06c2011-01-05 15:29:26 -080076 // For #pragma version
77 PP.AddPragmaHandler(RSPragmaHandler::CreatePragmaVersionHandler(this));
78
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070079 // Prepare target data
Stephen Hines9e5b5032010-11-03 13:19:14 -070080 mTargetData = new llvm::TargetData(Target.getTargetDescription());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070081
82 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070083}
84
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070085bool RSContext::processExportVar(const clang::VarDecl *VD) {
Stephen Hines6e6578a2011-02-07 18:05:48 -080086 slangAssert(!VD->getName().empty() && "Variable name should not be empty");
Shih-wei Liao462aefd2010-06-04 15:32:04 -070087
zonr6315f762010-10-05 15:35:14 +080088 // TODO(zonr): some check on variable
Shih-wei Liao462aefd2010-06-04 15:32:04 -070089
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070090 RSExportType *ET = RSExportType::CreateFromDecl(this, VD);
91 if (!ET)
92 return false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070093
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070094 RSExportVar *EV = new RSExportVar(this, VD, ET);
95 if (EV == NULL)
96 return false;
97 else
98 mExportVars.push_back(EV);
Shih-wei Liao462aefd2010-06-04 15:32:04 -070099
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700100 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700101}
102
zonr6315f762010-10-05 15:35:14 +0800103bool RSContext::processExportFunc(const clang::FunctionDecl *FD) {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800104 slangAssert(!FD->getName().empty() && "Function name should not be empty");
Shih-wei Liao537446c2010-06-11 16:05:55 -0700105
Stephen Hines3fbe68a2010-11-17 17:28:59 -0800106 if (!FD->isThisDeclarationADefinition()) {
107 return true;
108 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700109
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700110 if (FD->getStorageClass() != clang::SC_None) {
111 fprintf(stderr, "RSContext::processExportFunc : cannot export extern or "
112 "static function '%s'\n", FD->getName().str().c_str());
113 return false;
114 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700115
Stephen Hines9999ec32012-02-10 18:22:14 -0800116 if (RSExportForEach::isSpecialRSFunc(mTargetAPI, FD)) {
117 // Do not reflect specialized functions like init, dtor, or graphics root.
118 return RSExportForEach::validateSpecialFuncDecl(mTargetAPI,
119 getDiagnostics(), FD);
120 } else if (RSExportForEach::isRSForEachFunc(mTargetAPI, FD)) {
Stephen Hines593a8942011-05-10 15:29:50 -0700121 RSExportForEach *EFE = RSExportForEach::Create(this, FD);
122 if (EFE == NULL)
123 return false;
124 else
125 mExportForEach.push_back(EFE);
126 return true;
Stephen Hines3fbe68a2010-11-17 17:28:59 -0800127 }
128
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700129 RSExportFunc *EF = RSExportFunc::Create(this, FD);
130 if (EF == NULL)
131 return false;
132 else
133 mExportFuncs.push_back(EF);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700134
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700135 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700136}
137
138
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700139bool RSContext::processExportType(const llvm::StringRef &Name) {
Stephen Hines9e5b5032010-11-03 13:19:14 -0700140 clang::TranslationUnitDecl *TUDecl = mCtx.getTranslationUnitDecl();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700141
Stephen Hines6e6578a2011-02-07 18:05:48 -0800142 slangAssert(TUDecl != NULL && "Translation unit declaration (top-level "
143 "declaration) is null object");
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700144
Stephen Hines9e5b5032010-11-03 13:19:14 -0700145 const clang::IdentifierInfo *II = mPP.getIdentifierInfo(Name);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700146 if (II == NULL)
zonr6315f762010-10-05 15:35:14 +0800147 // TODO(zonr): alert identifier @Name mark as an exportable type cannot be
148 // found
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700149 return false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700150
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700151 clang::DeclContext::lookup_const_result R = TUDecl->lookup(II);
152 RSExportType *ET = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700153
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700154 for (clang::DeclContext::lookup_const_iterator I = R.first, E = R.second;
155 I != E;
156 I++) {
157 clang::NamedDecl *const ND = *I;
158 const clang::Type *T = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700159
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700160 switch (ND->getKind()) {
161 case clang::Decl::Typedef: {
162 T = static_cast<const clang::TypedefDecl*>(
163 ND)->getCanonicalDecl()->getUnderlyingType().getTypePtr();
164 break;
165 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700166 case clang::Decl::Record: {
167 T = static_cast<const clang::RecordDecl*>(ND)->getTypeForDecl();
168 break;
169 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700170 default: {
171 // unsupported, skip
172 break;
Shih-wei Liaoac918152010-08-29 02:43:24 -0700173 }
174 }
Shih-wei Liao537446c2010-06-11 16:05:55 -0700175
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700176 if (T != NULL)
177 ET = RSExportType::Create(this, T);
178 }
179
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700180 return (ET != NULL);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700181}
182
Stephen Hinesc17e1982012-02-22 12:30:45 -0800183
184// Possibly re-order ForEach exports (maybe generating a dummy "root" function).
185// We require "root" to be listed as slot 0 of our exported compute kernels,
186// so this only needs to be created if we have other non-root kernels.
187void RSContext::cleanupForEach() {
188 bool foundNonRoot = false;
189 ExportForEachList::iterator begin = mExportForEach.begin();
190
191 for (ExportForEachList::iterator I = begin, E = mExportForEach.end();
192 I != E;
193 I++) {
194 RSExportForEach *EFE = *I;
195 if (!EFE->getName().compare("root")) {
196 if (I == begin) {
197 // Nothing to do, since it is the first function
198 return;
199 }
200
201 mExportForEach.erase(I);
202 mExportForEach.push_front(EFE);
203 return;
204 } else {
205 foundNonRoot = true;
206 }
207 }
208
209 // If we found a non-root kernel, but no root() function, we need to add a
210 // dummy version (so that script->script calls of rsForEach don't behave
211 // erratically).
212 if (foundNonRoot) {
213 RSExportForEach *DummyRoot = RSExportForEach::CreateDummyRoot(this);
214 mExportForEach.push_front(DummyRoot);
215 }
216}
217
218
Stephen Hinesc808a992010-11-29 17:20:42 -0800219bool RSContext::processExport() {
Stephen Hinesb6809ed2011-05-09 13:05:04 -0700220 bool valid = true;
Stephen Hines593a8942011-05-10 15:29:50 -0700221
222 if (getDiagnostics()->hasErrorOccurred()) {
223 return false;
224 }
225
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700226 // Export variable
Stephen Hines9e5b5032010-11-03 13:19:14 -0700227 clang::TranslationUnitDecl *TUDecl = mCtx.getTranslationUnitDecl();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700228 for (clang::DeclContext::decl_iterator DI = TUDecl->decls_begin(),
229 DE = TUDecl->decls_end();
Stephen Hinesc97a3332010-11-30 15:31:08 -0800230 DI != DE;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700231 DI++) {
232 if (DI->getKind() == clang::Decl::Var) {
233 clang::VarDecl *VD = (clang::VarDecl*) (*DI);
Stephen Hines2d2512c2010-11-18 18:54:21 -0800234 if (VD->getLinkage() == clang::ExternalLinkage) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700235 if (!processExportVar(VD)) {
Stephen Hinesb6809ed2011-05-09 13:05:04 -0700236 valid = false;
Ying Wang3f8b44d2010-09-04 01:17:01 -0700237 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700238 }
239 } else if (DI->getKind() == clang::Decl::Function) {
240 // Export functions
241 clang::FunctionDecl *FD = (clang::FunctionDecl*) (*DI);
Stephen Hines2d2512c2010-11-18 18:54:21 -0800242 if (FD->getLinkage() == clang::ExternalLinkage) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700243 if (!processExportFunc(FD)) {
Stephen Hinesb6809ed2011-05-09 13:05:04 -0700244 valid = false;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700245 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700246 }
Ying Wang3f8b44d2010-09-04 01:17:01 -0700247 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700248 }
Ying Wang3f8b44d2010-09-04 01:17:01 -0700249
Stephen Hinesc17e1982012-02-22 12:30:45 -0800250 if (valid) {
251 cleanupForEach();
252 }
253
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700254 // Finally, export type forcely set to be exported by user
255 for (NeedExportTypeSet::const_iterator EI = mNeedExportTypes.begin(),
256 EE = mNeedExportTypes.end();
257 EI != EE;
258 EI++) {
259 if (!processExportType(EI->getKey())) {
Stephen Hinesb6809ed2011-05-09 13:05:04 -0700260 valid = false;
Ying Wang3f8b44d2010-09-04 01:17:01 -0700261 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700262 }
Shih-wei Liao537446c2010-06-11 16:05:55 -0700263
Stephen Hinesb6809ed2011-05-09 13:05:04 -0700264 return valid;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700265}
266
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700267bool RSContext::insertExportType(const llvm::StringRef &TypeName,
268 RSExportType *ET) {
269 ExportTypeMap::value_type *NewItem =
270 ExportTypeMap::value_type::Create(TypeName.begin(),
271 TypeName.end(),
272 mExportTypes.getAllocator(),
273 ET);
Shih-wei Liao6de89272010-07-15 15:26:20 -0700274
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700275 if (mExportTypes.insert(NewItem)) {
Shih-wei Liao6de89272010-07-15 15:26:20 -0700276 return true;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700277 } else {
278 free(NewItem);
279 return false;
280 }
281}
282
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700283bool RSContext::reflectToJava(const std::string &OutputPathBase,
284 const std::string &OutputPackageName,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700285 const std::string &InputFileName,
286 const std::string &OutputBCFileName,
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700287 std::string *RealPackageName) {
288 if (RealPackageName != NULL)
289 RealPackageName->clear();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700290
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700291 const std::string &PackageName =
292 ((OutputPackageName.empty()) ? mReflectJavaPackageName :
293 OutputPackageName);
Stephen Hines35f5b392010-11-22 16:39:16 -0800294 if (PackageName.empty()) {
Stephen Hines7aff4a02011-12-08 18:34:27 -0800295 clang::DiagnosticsEngine *DiagEngine = getDiagnostics();
296 const clang::SourceManager *SM = getSourceManager();
297 DiagEngine->Report(
298 SM->getLocForEndOfFile(SM->getMainFileID()),
299 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
300 "missing \"#pragma rs "
301 "java_package_name(com.foo.bar)\" "
302 "in source file"));
Stephen Hines35f5b392010-11-22 16:39:16 -0800303 return false;
304 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700305
306 // Copy back the really applied package name
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700307 RealPackageName->assign(PackageName);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700308
Stephen Hines4cc67fc2011-01-31 16:48:57 -0800309 RSReflection *R = new RSReflection(this, mGeneratedFileNames);
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700310 bool ret = R->reflect(OutputPathBase, PackageName,
311 InputFileName, OutputBCFileName);
zonr6315f762010-10-05 15:35:14 +0800312 if (!ret)
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700313 fprintf(stderr, "RSContext::reflectToJava : failed to do reflection "
314 "(%s)\n", R->getLastError());
315 delete R;
316 return ret;
317}
318
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700319RSContext::~RSContext() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700320 delete mLicenseNote;
321 delete mTargetData;
Zonr Changa41ce1d2010-10-06 02:23:12 +0800322 for (ExportableList::iterator I = mExportables.begin(),
323 E = mExportables.end();
324 I != E;
325 I++) {
Zonr Chang641558f2010-10-12 21:07:06 +0800326 if (!(*I)->isKeep())
327 delete *I;
Zonr Changa41ce1d2010-10-06 02:23:12 +0800328 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700329}
Stephen Hinese639eb52010-11-08 19:27:20 -0800330
331} // namespace slang