blob: 94eb6bebc6e2db8ca3fe5224b35054d58c3c4eae [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
Stephen Hines23c43582013-01-09 20:02:04 -080030#include "llvm/IR/LLVMContext.h"
31#include "llvm/IR/DataLayout.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"
Matt Walac0c5dd82015-07-23 17:29:37 -070037#include "slang_rs_export_reduce.h"
zonr6315f762010-10-05 15:35:14 +080038#include "slang_rs_export_type.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080039#include "slang_rs_export_var.h"
40#include "slang_rs_exportable.h"
zonr6315f762010-10-05 15:35:14 +080041#include "slang_rs_pragma_handler.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080042#include "slang_rs_reflection.h"
Matt Walaeae0b7a2015-06-16 14:06:25 -070043#include "slang_rs_special_func.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070044
Stephen Hinese639eb52010-11-08 19:27:20 -080045namespace slang {
Shih-wei Liao462aefd2010-06-04 15:32:04 -070046
Stephen Hines9e5b5032010-11-03 13:19:14 -070047RSContext::RSContext(clang::Preprocessor &PP,
48 clang::ASTContext &Ctx,
Stephen Hines3fd0a942011-01-18 12:27:39 -080049 const clang::TargetInfo &Target,
Stephen Hines4cc67fc2011-01-31 16:48:57 -080050 PragmaList *Pragmas,
Stephen Hinesfc4f78b2014-06-10 18:07:10 -070051 unsigned int TargetAPI,
52 bool Verbose)
zonr6315f762010-10-05 15:35:14 +080053 : mPP(PP),
54 mCtx(Ctx),
Stephen Hines3fd0a942011-01-18 12:27:39 -080055 mPragmas(Pragmas),
Stephen Hines4a4bf922011-08-18 17:20:33 -070056 mTargetAPI(TargetAPI),
Stephen Hinesfc4f78b2014-06-10 18:07:10 -070057 mVerbose(Verbose),
Chris Wailes5abbe0e2014-08-12 15:58:29 -070058 mDataLayout(nullptr),
zonr6315f762010-10-05 15:35:14 +080059 mLLVMContext(llvm::getGlobalContext()),
Chris Wailes5abbe0e2014-08-12 15:58:29 -070060 mLicenseNote(nullptr),
Stephen Hines0a813a32012-08-03 16:52:40 -070061 mRSPackageName("android.renderscript"),
Shih-wei Liao3fa286b2011-02-10 11:04:44 -080062 version(0),
Stephen Hines9ae18b22014-06-10 23:53:00 -070063 mMangleCtx(Ctx.createMangleContext()),
64 mIs64Bit(Target.getPointerWidth(0) == 64) {
Stephen Hines4cc67fc2011-01-31 16:48:57 -080065
Jean-Luc Brouillet109e90a2014-07-07 17:36:07 -070066 AddPragmaHandlers(PP, this);
Stephen Hines96ab06c2011-01-05 15:29:26 -080067
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070068 // Prepare target data
Stephen Hines23c43582013-01-09 20:02:04 -080069 mDataLayout = new llvm::DataLayout(Target.getTargetDescription());
Shih-wei Liao462aefd2010-06-04 15:32:04 -070070}
71
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070072bool RSContext::processExportVar(const clang::VarDecl *VD) {
Stephen Hines6e6578a2011-02-07 18:05:48 -080073 slangAssert(!VD->getName().empty() && "Variable name should not be empty");
Shih-wei Liao462aefd2010-06-04 15:32:04 -070074
zonr6315f762010-10-05 15:35:14 +080075 // TODO(zonr): some check on variable
Shih-wei Liao462aefd2010-06-04 15:32:04 -070076
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070077 RSExportType *ET = RSExportType::CreateFromDecl(this, VD);
78 if (!ET)
79 return false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070080
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070081 RSExportVar *EV = new RSExportVar(this, VD, ET);
Chris Wailes5abbe0e2014-08-12 15:58:29 -070082 if (EV == nullptr)
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070083 return false;
84 else
85 mExportVars.push_back(EV);
Shih-wei Liao462aefd2010-06-04 15:32:04 -070086
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070087 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070088}
89
zonr6315f762010-10-05 15:35:14 +080090bool RSContext::processExportFunc(const clang::FunctionDecl *FD) {
Stephen Hines6e6578a2011-02-07 18:05:48 -080091 slangAssert(!FD->getName().empty() && "Function name should not be empty");
Shih-wei Liao537446c2010-06-11 16:05:55 -070092
Stephen Hines3fbe68a2010-11-17 17:28:59 -080093 if (!FD->isThisDeclarationADefinition()) {
94 return true;
95 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -070096
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070097 if (FD->getStorageClass() != clang::SC_None) {
98 fprintf(stderr, "RSContext::processExportFunc : cannot export extern or "
99 "static function '%s'\n", FD->getName().str().c_str());
100 return false;
101 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700102
Matt Walac0c5dd82015-07-23 17:29:37 -0700103 // Specialized function
Matt Walaeae0b7a2015-06-16 14:06:25 -0700104 if (RSSpecialFunc::isSpecialRSFunc(mTargetAPI, FD)) {
Stephen Hines9999ec32012-02-10 18:22:14 -0800105 // Do not reflect specialized functions like init, dtor, or graphics root.
Matt Walaeae0b7a2015-06-16 14:06:25 -0700106 return RSSpecialFunc::validateSpecialFuncDecl(mTargetAPI, this, FD);
Matt Walac0c5dd82015-07-23 17:29:37 -0700107 }
108
109 // Foreach kernel
110 if (RSExportForEach::isRSForEachFunc(mTargetAPI, FD)) {
Stephen Hines5d9263d2015-10-13 20:07:52 +0000111 if (auto *EFE = RSExportForEach::Create(this, FD)) {
112 mExportForEach.push_back(EFE);
113 return true;
114 }
115 return false;
Matt Walac0c5dd82015-07-23 17:29:37 -0700116 }
117
118 // Reduce kernel
119 if (RSExportReduce::isRSReduceFunc(mTargetAPI, FD)) {
120 if (auto *ER = RSExportReduce::Create(this, FD)) {
121 mExportReduce.push_back(ER);
122 return true;
123 }
124 return false;
125 }
126
127 // Invokable
128 if (auto *EF = RSExportFunc::Create(this, FD)) {
129 mExportFuncs.push_back(EF);
Stephen Hines593a8942011-05-10 15:29:50 -0700130 return true;
Stephen Hines3fbe68a2010-11-17 17:28:59 -0800131 }
132
Matt Walac0c5dd82015-07-23 17:29:37 -0700133 return false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700134}
135
136
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700137bool RSContext::processExportType(const llvm::StringRef &Name) {
Stephen Hines9e5b5032010-11-03 13:19:14 -0700138 clang::TranslationUnitDecl *TUDecl = mCtx.getTranslationUnitDecl();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700139
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700140 slangAssert(TUDecl != nullptr && "Translation unit declaration (top-level "
141 "declaration) is null object");
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700142
Stephen Hines9e5b5032010-11-03 13:19:14 -0700143 const clang::IdentifierInfo *II = mPP.getIdentifierInfo(Name);
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700144 if (II == nullptr)
zonr6315f762010-10-05 15:35:14 +0800145 // TODO(zonr): alert identifier @Name mark as an exportable type cannot be
146 // found
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700147 return false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700148
Stephen Hinesc7069072015-03-18 14:53:14 -0700149 clang::DeclContext::lookup_result R = TUDecl->lookup(II);
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700150 RSExportType *ET = nullptr;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700151
Stephen Hinesc7069072015-03-18 14:53:14 -0700152 for (clang::DeclContext::lookup_iterator I = R.begin(), E = R.end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700153 I != E;
154 I++) {
155 clang::NamedDecl *const ND = *I;
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700156 const clang::Type *T = nullptr;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700157
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700158 switch (ND->getKind()) {
159 case clang::Decl::Typedef: {
160 T = static_cast<const clang::TypedefDecl*>(
161 ND)->getCanonicalDecl()->getUnderlyingType().getTypePtr();
162 break;
163 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700164 case clang::Decl::Record: {
165 T = static_cast<const clang::RecordDecl*>(ND)->getTypeForDecl();
166 break;
167 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700168 default: {
169 // unsupported, skip
170 break;
Shih-wei Liaoac918152010-08-29 02:43:24 -0700171 }
172 }
Shih-wei Liao537446c2010-06-11 16:05:55 -0700173
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700174 if (T != nullptr)
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700175 ET = RSExportType::Create(this, T);
176 }
177
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700178 return (ET != nullptr);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700179}
180
Stephen Hinesc17e1982012-02-22 12:30:45 -0800181
Stephen Hines5d9263d2015-10-13 20:07:52 +0000182// Possibly re-order ForEach exports (maybe generating a dummy "root" function).
183// We require "root" to be listed as slot 0 of our exported compute kernels,
184// so this only needs to be created if we have other non-root kernels.
185void RSContext::cleanupForEach() {
186 bool foundNonRoot = false;
187 ExportForEachList::iterator begin = mExportForEach.begin();
188
189 for (ExportForEachList::iterator I = begin, E = mExportForEach.end();
190 I != E;
191 I++) {
192 RSExportForEach *EFE = *I;
193 if (!EFE->getName().compare("root")) {
194 if (I == begin) {
195 // Nothing to do, since it is the first function
196 return;
Yang Ni45aa8c52015-09-14 14:55:20 -0700197 }
Stephen Hines5d9263d2015-10-13 20:07:52 +0000198
199 mExportForEach.erase(I);
200 mExportForEach.push_front(EFE);
201 return;
202 } else {
203 foundNonRoot = true;
Yang Ni45aa8c52015-09-14 14:55:20 -0700204 }
205 }
Stephen Hines5d9263d2015-10-13 20:07:52 +0000206
207 // If we found a non-root kernel, but no root() function, we need to add a
208 // dummy version (so that script->script calls of rsForEach don't behave
209 // erratically).
210 if (foundNonRoot) {
211 RSExportForEach *DummyRoot = RSExportForEach::CreateDummyRoot(this);
212 mExportForEach.push_front(DummyRoot);
213 }
Yang Ni45aa8c52015-09-14 14:55:20 -0700214}
Stephen Hinesc17e1982012-02-22 12:30:45 -0800215
Stephen Hines5d9263d2015-10-13 20:07:52 +0000216
Stephen Hinesc808a992010-11-29 17:20:42 -0800217bool RSContext::processExport() {
Stephen Hinesb6809ed2011-05-09 13:05:04 -0700218 bool valid = true;
Stephen Hines593a8942011-05-10 15:29:50 -0700219
220 if (getDiagnostics()->hasErrorOccurred()) {
221 return false;
222 }
223
Stephen Hines5d9263d2015-10-13 20:07:52 +0000224 // Export variable
225 clang::TranslationUnitDecl *TUDecl = mCtx.getTranslationUnitDecl();
226 for (clang::DeclContext::decl_iterator DI = TUDecl->decls_begin(),
227 DE = TUDecl->decls_end();
228 DI != DE;
229 DI++) {
230 if (DI->getKind() == clang::Decl::Var) {
231 clang::VarDecl *VD = (clang::VarDecl*) (*DI);
232 if (VD->getFormalLinkage() == clang::ExternalLinkage) {
233 if (!processExportVar(VD)) {
234 valid = false;
235 }
236 }
237 } else if (DI->getKind() == clang::Decl::Function) {
238 // Export functions
239 clang::FunctionDecl *FD = (clang::FunctionDecl*) (*DI);
240 if (FD->getFormalLinkage() == clang::ExternalLinkage) {
241 if (!processExportFunc(FD)) {
242 valid = false;
243 }
244 }
245 }
246 }
247
248 if (valid) {
249 cleanupForEach();
Stephen Hinesc17e1982012-02-22 12:30:45 -0800250 }
251
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700252 // Finally, export type forcely set to be exported by user
253 for (NeedExportTypeSet::const_iterator EI = mNeedExportTypes.begin(),
254 EE = mNeedExportTypes.end();
255 EI != EE;
256 EI++) {
257 if (!processExportType(EI->getKey())) {
Stephen Hinesb6809ed2011-05-09 13:05:04 -0700258 valid = false;
Ying Wang3f8b44d2010-09-04 01:17:01 -0700259 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700260 }
Shih-wei Liao537446c2010-06-11 16:05:55 -0700261
Stephen Hinesb6809ed2011-05-09 13:05:04 -0700262 return valid;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700263}
264
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700265bool RSContext::insertExportType(const llvm::StringRef &TypeName,
266 RSExportType *ET) {
267 ExportTypeMap::value_type *NewItem =
Stephen Hines2eb9a3f2014-07-15 16:50:03 -0700268 ExportTypeMap::value_type::Create(TypeName,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700269 mExportTypes.getAllocator(),
270 ET);
Shih-wei Liao6de89272010-07-15 15:26:20 -0700271
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700272 if (mExportTypes.insert(NewItem)) {
Shih-wei Liao6de89272010-07-15 15:26:20 -0700273 return true;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700274 } else {
Matt Wala3f45a252015-06-30 11:24:19 -0700275 NewItem->Destroy(mExportTypes.getAllocator());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700276 return false;
277 }
278}
279
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700280RSContext::~RSContext() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700281 delete mLicenseNote;
Stephen Hines23c43582013-01-09 20:02:04 -0800282 delete mDataLayout;
Zonr Changa41ce1d2010-10-06 02:23:12 +0800283 for (ExportableList::iterator I = mExportables.begin(),
284 E = mExportables.end();
285 I != E;
286 I++) {
Zonr Chang641558f2010-10-12 21:07:06 +0800287 if (!(*I)->isKeep())
288 delete *I;
Zonr Changa41ce1d2010-10-06 02:23:12 +0800289 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700290}
Stephen Hinese639eb52010-11-08 19:27:20 -0800291
292} // namespace slang