blob: bc674a0cf731f1dd1f277fad4d396671a3b3cd40 [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"
Yang Nifb40ee22015-10-13 20:34:06 +000022#include "clang/AST/Attr.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080023#include "clang/AST/Decl.h"
24#include "clang/AST/DeclBase.h"
Loganbe274822011-02-16 22:02:54 +080025#include "clang/AST/Mangle.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080026#include "clang/AST/Type.h"
27
28#include "clang/Basic/Linkage.h"
29#include "clang/Basic/TargetInfo.h"
30
Stephen Hines23c43582013-01-09 20:02:04 -080031#include "llvm/IR/LLVMContext.h"
32#include "llvm/IR/DataLayout.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070033
zonr6315f762010-10-05 15:35:14 +080034#include "slang.h"
Stephen Hines6e6578a2011-02-07 18:05:48 -080035#include "slang_assert.h"
Stephen Hines593a8942011-05-10 15:29:50 -070036#include "slang_rs_export_foreach.h"
zonr6315f762010-10-05 15:35:14 +080037#include "slang_rs_export_func.h"
Matt Walac0c5dd82015-07-23 17:29:37 -070038#include "slang_rs_export_reduce.h"
zonr6315f762010-10-05 15:35:14 +080039#include "slang_rs_export_type.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080040#include "slang_rs_export_var.h"
41#include "slang_rs_exportable.h"
zonr6315f762010-10-05 15:35:14 +080042#include "slang_rs_pragma_handler.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080043#include "slang_rs_reflection.h"
Matt Walaeae0b7a2015-06-16 14:06:25 -070044#include "slang_rs_special_func.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070045
Stephen Hinese639eb52010-11-08 19:27:20 -080046namespace slang {
Shih-wei Liao462aefd2010-06-04 15:32:04 -070047
Stephen Hines9e5b5032010-11-03 13:19:14 -070048RSContext::RSContext(clang::Preprocessor &PP,
49 clang::ASTContext &Ctx,
Stephen Hines3fd0a942011-01-18 12:27:39 -080050 const clang::TargetInfo &Target,
Stephen Hines4cc67fc2011-01-31 16:48:57 -080051 PragmaList *Pragmas,
Stephen Hinesfc4f78b2014-06-10 18:07:10 -070052 unsigned int TargetAPI,
53 bool Verbose)
zonr6315f762010-10-05 15:35:14 +080054 : mPP(PP),
55 mCtx(Ctx),
Stephen Hines3fd0a942011-01-18 12:27:39 -080056 mPragmas(Pragmas),
Stephen Hines4a4bf922011-08-18 17:20:33 -070057 mTargetAPI(TargetAPI),
Stephen Hinesfc4f78b2014-06-10 18:07:10 -070058 mVerbose(Verbose),
Chris Wailes5abbe0e2014-08-12 15:58:29 -070059 mDataLayout(nullptr),
zonr6315f762010-10-05 15:35:14 +080060 mLLVMContext(llvm::getGlobalContext()),
Chris Wailes5abbe0e2014-08-12 15:58:29 -070061 mLicenseNote(nullptr),
Stephen Hines0a813a32012-08-03 16:52:40 -070062 mRSPackageName("android.renderscript"),
Shih-wei Liao3fa286b2011-02-10 11:04:44 -080063 version(0),
Stephen Hines9ae18b22014-06-10 23:53:00 -070064 mMangleCtx(Ctx.createMangleContext()),
Yang Nifb40ee22015-10-13 20:34:06 +000065 mIs64Bit(Target.getPointerWidth(0) == 64),
66 mNextSlot(1) {
Stephen Hines4cc67fc2011-01-31 16:48:57 -080067
Jean-Luc Brouillet109e90a2014-07-07 17:36:07 -070068 AddPragmaHandlers(PP, this);
Stephen Hines96ab06c2011-01-05 15:29:26 -080069
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070070 // Prepare target data
Stephen Hines23c43582013-01-09 20:02:04 -080071 mDataLayout = new llvm::DataLayout(Target.getTargetDescription());
Yang Nifb40ee22015-10-13 20:34:06 +000072
73 // Reserve slot 0 for the root kernel.
74 mExportForEach.push_back(nullptr);
Shih-wei Liao462aefd2010-06-04 15:32:04 -070075}
76
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070077bool RSContext::processExportVar(const clang::VarDecl *VD) {
Stephen Hines6e6578a2011-02-07 18:05:48 -080078 slangAssert(!VD->getName().empty() && "Variable name should not be empty");
Shih-wei Liao462aefd2010-06-04 15:32:04 -070079
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070080 RSExportType *ET = RSExportType::CreateFromDecl(this, VD);
81 if (!ET)
82 return false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070083
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070084 RSExportVar *EV = new RSExportVar(this, VD, ET);
Chris Wailes5abbe0e2014-08-12 15:58:29 -070085 if (EV == nullptr)
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070086 return false;
87 else
88 mExportVars.push_back(EV);
Shih-wei Liao462aefd2010-06-04 15:32:04 -070089
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070090 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070091}
92
Yang Nifb40ee22015-10-13 20:34:06 +000093int RSContext::getForEachSlotNumber(const clang::FunctionDecl* FD) {
94 const clang::StringRef& funcName = FD->getName();
95 return getForEachSlotNumber(funcName);
96}
97
98int RSContext::getForEachSlotNumber(const clang::StringRef& funcName) {
99 auto it = mExportForEachMap.find(funcName);
100 if (it == mExportForEachMap.end()) {
101 return -1;
102 }
103 return it->second;
104}
105
zonr6315f762010-10-05 15:35:14 +0800106bool RSContext::processExportFunc(const clang::FunctionDecl *FD) {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800107 slangAssert(!FD->getName().empty() && "Function name should not be empty");
Shih-wei Liao537446c2010-06-11 16:05:55 -0700108
Stephen Hines3fbe68a2010-11-17 17:28:59 -0800109 if (!FD->isThisDeclarationADefinition()) {
110 return true;
111 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700112
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700113 if (FD->getStorageClass() != clang::SC_None) {
114 fprintf(stderr, "RSContext::processExportFunc : cannot export extern or "
115 "static function '%s'\n", FD->getName().str().c_str());
116 return false;
117 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700118
Matt Walac0c5dd82015-07-23 17:29:37 -0700119 // Specialized function
Matt Walaeae0b7a2015-06-16 14:06:25 -0700120 if (RSSpecialFunc::isSpecialRSFunc(mTargetAPI, FD)) {
Stephen Hines9999ec32012-02-10 18:22:14 -0800121 // Do not reflect specialized functions like init, dtor, or graphics root.
Matt Walaeae0b7a2015-06-16 14:06:25 -0700122 return RSSpecialFunc::validateSpecialFuncDecl(mTargetAPI, this, FD);
Matt Walac0c5dd82015-07-23 17:29:37 -0700123 }
124
125 // Foreach kernel
126 if (RSExportForEach::isRSForEachFunc(mTargetAPI, FD)) {
Yang Nifb40ee22015-10-13 20:34:06 +0000127 RSExportForEach *EFE = RSExportForEach::Create(this, FD);
128 if (EFE == nullptr) {
129 return false;
Stephen Hines5d9263d2015-10-13 20:07:52 +0000130 }
Yang Nifb40ee22015-10-13 20:34:06 +0000131 const llvm::StringRef& funcName = FD->getName();
132 if (funcName.equals("root")) {
133 mExportForEach[0] = EFE;
134 } else {
135 mExportForEach.push_back(EFE);
136 }
137 return true;
Matt Walac0c5dd82015-07-23 17:29:37 -0700138 }
139
140 // Reduce kernel
141 if (RSExportReduce::isRSReduceFunc(mTargetAPI, FD)) {
142 if (auto *ER = RSExportReduce::Create(this, FD)) {
143 mExportReduce.push_back(ER);
144 return true;
145 }
146 return false;
147 }
148
149 // Invokable
150 if (auto *EF = RSExportFunc::Create(this, FD)) {
151 mExportFuncs.push_back(EF);
Stephen Hines593a8942011-05-10 15:29:50 -0700152 return true;
Stephen Hines3fbe68a2010-11-17 17:28:59 -0800153 }
154
Matt Walac0c5dd82015-07-23 17:29:37 -0700155 return false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700156}
157
Yang Nifb40ee22015-10-13 20:34:06 +0000158bool RSContext::addForEach(const clang::FunctionDecl* FD) {
159 const llvm::StringRef& funcName = FD->getName();
160
161 if (funcName.equals("root")) {
162 // The root kernel should always be in slot 0.
163 mExportForEachMap.insert(std::make_pair(funcName, 0));
164 } else {
165 mExportForEachMap.insert(std::make_pair(funcName, mNextSlot++));
166 }
167
168 return true;
169}
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700170
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700171bool RSContext::processExportType(const llvm::StringRef &Name) {
Stephen Hines9e5b5032010-11-03 13:19:14 -0700172 clang::TranslationUnitDecl *TUDecl = mCtx.getTranslationUnitDecl();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700173
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700174 slangAssert(TUDecl != nullptr && "Translation unit declaration (top-level "
175 "declaration) is null object");
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700176
Stephen Hines9e5b5032010-11-03 13:19:14 -0700177 const clang::IdentifierInfo *II = mPP.getIdentifierInfo(Name);
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700178 if (II == nullptr)
zonr6315f762010-10-05 15:35:14 +0800179 // TODO(zonr): alert identifier @Name mark as an exportable type cannot be
180 // found
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700181 return false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700182
Stephen Hinesc7069072015-03-18 14:53:14 -0700183 clang::DeclContext::lookup_result R = TUDecl->lookup(II);
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700184 RSExportType *ET = nullptr;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700185
Stephen Hinesc7069072015-03-18 14:53:14 -0700186 for (clang::DeclContext::lookup_iterator I = R.begin(), E = R.end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700187 I != E;
188 I++) {
189 clang::NamedDecl *const ND = *I;
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700190 const clang::Type *T = nullptr;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700191
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700192 switch (ND->getKind()) {
193 case clang::Decl::Typedef: {
194 T = static_cast<const clang::TypedefDecl*>(
195 ND)->getCanonicalDecl()->getUnderlyingType().getTypePtr();
196 break;
197 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700198 case clang::Decl::Record: {
199 T = static_cast<const clang::RecordDecl*>(ND)->getTypeForDecl();
200 break;
201 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700202 default: {
203 // unsupported, skip
204 break;
Shih-wei Liaoac918152010-08-29 02:43:24 -0700205 }
206 }
Shih-wei Liao537446c2010-06-11 16:05:55 -0700207
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700208 if (T != nullptr)
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700209 ET = RSExportType::Create(this, T);
210 }
211
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700212 return (ET != nullptr);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700213}
214
Yang Nifb40ee22015-10-13 20:34:06 +0000215void RSContext::addAllocationType(const clang::TypeDecl* TD) {
216 mAllocationType = mCtx.getTypeDeclType(TD);
Yang Ni45aa8c52015-09-14 14:55:20 -0700217}
Stephen Hinesc17e1982012-02-22 12:30:45 -0800218
Yang Nifb40ee22015-10-13 20:34:06 +0000219bool RSContext::processExports() {
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
Stephen Hines5d9263d2015-10-13 20:07:52 +0000226 clang::TranslationUnitDecl *TUDecl = mCtx.getTranslationUnitDecl();
Yang Nifb40ee22015-10-13 20:34:06 +0000227 for (auto I = TUDecl->decls_begin(), E = TUDecl->decls_end(); I != E; I++) {
228 clang::Decl* D = *I;
229 switch (D->getKind()) {
230 case clang::Decl::Var: {
231 clang::VarDecl* VD = llvm::dyn_cast<clang::VarDecl>(D);
Stephen Hinesa5d846d2015-10-08 20:06:26 -0700232 bool ShouldExportVariable = true;
Stephen Hines5d9263d2015-10-13 20:07:52 +0000233 if (VD->getFormalLinkage() == clang::ExternalLinkage) {
Stephen Hinesa5d846d2015-10-08 20:06:26 -0700234 clang::QualType QT = VD->getTypeSourceInfo()->getType();
235 if (QT.isConstQualified() && !VD->hasInit()) {
236 if (Slang::IsLocInRSHeaderFile(VD->getLocation(),
237 *getSourceManager())) {
238 // We don't export variables internal to the runtime's
239 // implementation.
240 ShouldExportVariable = false;
241 } else {
242 clang::DiagnosticsEngine *DiagEngine = getDiagnostics();
243 DiagEngine->Report(VD->getLocation(), DiagEngine->getCustomDiagID(
244 clang::DiagnosticsEngine::Error,
245 "invalid declaration of uninitialized constant variable '%0'"))
246 << VD->getName();
247 valid = false;
248 }
249 }
250 if (valid && ShouldExportVariable && !processExportVar(VD)) {
Stephen Hines5d9263d2015-10-13 20:07:52 +0000251 valid = false;
252 }
253 }
Yang Nifb40ee22015-10-13 20:34:06 +0000254 break;
255 }
256 case clang::Decl::Function: {
257 clang::FunctionDecl* FD = llvm::dyn_cast<clang::FunctionDecl>(D);
Stephen Hines5d9263d2015-10-13 20:07:52 +0000258 if (FD->getFormalLinkage() == clang::ExternalLinkage) {
259 if (!processExportFunc(FD)) {
260 valid = false;
261 }
262 }
Yang Nifb40ee22015-10-13 20:34:06 +0000263 break;
264 }
265 default:
266 break;
Stephen Hines5d9263d2015-10-13 20:07:52 +0000267 }
268 }
269
Yang Nifb40ee22015-10-13 20:34:06 +0000270 // Create a dummy root in slot 0 if a root kernel is not seen.
271 if (valid && mExportForEach[0] == nullptr) {
272 mExportForEach[0] = RSExportForEach::CreateDummyRoot(this);
Stephen Hinesc17e1982012-02-22 12:30:45 -0800273 }
274
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700275 // Finally, export type forcely set to be exported by user
276 for (NeedExportTypeSet::const_iterator EI = mNeedExportTypes.begin(),
277 EE = mNeedExportTypes.end();
278 EI != EE;
279 EI++) {
280 if (!processExportType(EI->getKey())) {
Stephen Hinesb6809ed2011-05-09 13:05:04 -0700281 valid = false;
Ying Wang3f8b44d2010-09-04 01:17:01 -0700282 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700283 }
Shih-wei Liao537446c2010-06-11 16:05:55 -0700284
Stephen Hinesb6809ed2011-05-09 13:05:04 -0700285 return valid;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700286}
287
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700288bool RSContext::insertExportType(const llvm::StringRef &TypeName,
289 RSExportType *ET) {
290 ExportTypeMap::value_type *NewItem =
Stephen Hines2eb9a3f2014-07-15 16:50:03 -0700291 ExportTypeMap::value_type::Create(TypeName,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700292 mExportTypes.getAllocator(),
293 ET);
Shih-wei Liao6de89272010-07-15 15:26:20 -0700294
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700295 if (mExportTypes.insert(NewItem)) {
Shih-wei Liao6de89272010-07-15 15:26:20 -0700296 return true;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700297 } else {
Matt Wala3f45a252015-06-30 11:24:19 -0700298 NewItem->Destroy(mExportTypes.getAllocator());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700299 return false;
300 }
301}
302
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700303RSContext::~RSContext() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700304 delete mLicenseNote;
Stephen Hines23c43582013-01-09 20:02:04 -0800305 delete mDataLayout;
Zonr Changa41ce1d2010-10-06 02:23:12 +0800306 for (ExportableList::iterator I = mExportables.begin(),
307 E = mExportables.end();
308 I != E;
309 I++) {
Zonr Chang641558f2010-10-12 21:07:06 +0800310 if (!(*I)->isKeep())
311 delete *I;
Zonr Changa41ce1d2010-10-06 02:23:12 +0800312 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700313}
Stephen Hinese639eb52010-11-08 19:27:20 -0800314
315} // namespace slang