blob: 59478f0e8e9a156a360392bc24c672dd1b44553c [file] [log] [blame]
zonr6315f762010-10-05 15:35:14 +08001#include "slang_rs_context.h"
2
3#include "llvm/LLVMContext.h"
4#include "llvm/Target/TargetData.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -07005
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07006#include "clang/Basic/TargetInfo.h"
7#include "clang/Basic/Linkage.h"
8#include "clang/AST/Type.h"
9#include "clang/AST/Decl.h"
10#include "clang/AST/DeclBase.h"
11#include "clang/AST/ASTContext.h"
12#include "clang/Index/ASTLocation.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070013
zonr6315f762010-10-05 15:35:14 +080014#include "slang.h"
15#include "slang_rs_reflection.h"
Zonr Changa41ce1d2010-10-06 02:23:12 +080016#include "slang_rs_exportable.h"
zonr6315f762010-10-05 15:35:14 +080017#include "slang_rs_export_var.h"
18#include "slang_rs_export_func.h"
19#include "slang_rs_export_type.h"
20#include "slang_rs_pragma_handler.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070021
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070022using namespace slang;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070023
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070024RSContext::RSContext(clang::Preprocessor *PP,
25 clang::ASTContext *Ctx,
zonr6315f762010-10-05 15:35:14 +080026 const clang::TargetInfo *Target)
27 : mPP(PP),
28 mCtx(Ctx),
29 mTarget(Target),
30 mTargetData(NULL),
31 mLLVMContext(llvm::getGlobalContext()),
32 mExportAllNonStaticVars(false),
33 mExportAllNonStaticFuncs(false),
34 mLicenseNote(NULL) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070035 // For #pragma rs export_var
36 PP->AddPragmaHandler(
37 "rs", RSPragmaHandler::CreatePragmaExportVarHandler(this));
Shih-wei Liao462aefd2010-06-04 15:32:04 -070038
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070039 // For #pragma rs export_var_all
40 PP->AddPragmaHandler(
41 "rs", RSPragmaHandler::CreatePragmaExportVarAllHandler(this));
Victor Hsiehc6718b32010-06-23 09:29:44 +080042
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070043 // For #pragma rs export_func
44 PP->AddPragmaHandler(
45 "rs", RSPragmaHandler::CreatePragmaExportFuncHandler(this));
Victor Hsiehc6718b32010-06-23 09:29:44 +080046
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070047 // For #pragma rs export_func_all
48 PP->AddPragmaHandler(
49 "rs", RSPragmaHandler::CreatePragmaExportFuncAllHandler(this));
Shih-wei Liao537446c2010-06-11 16:05:55 -070050
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070051 // For #pragma rs export_type
52 PP->AddPragmaHandler(
53 "rs", RSPragmaHandler::CreatePragmaExportTypeHandler(this));
Victor Hsiehd8a0d182010-07-07 19:22:33 +080054
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070055 // For #pragma rs java_package_name
56 PP->AddPragmaHandler(
57 "rs", RSPragmaHandler::CreatePragmaJavaPackageNameHandler(this));
Shih-wei Liao462aefd2010-06-04 15:32:04 -070058
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070059 // For #pragma rs set_reflect_license
60 PP->AddPragmaHandler(
61 "rs", RSPragmaHandler::CreatePragmaReflectLicenseHandler(this));
62
63 // Prepare target data
64 mTargetData = new llvm::TargetData(Slang::TargetDescription);
65
66 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070067}
68
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070069bool RSContext::processExportVar(const clang::VarDecl *VD) {
70 assert(!VD->getName().empty() && "Variable name should not be empty");
Shih-wei Liao462aefd2010-06-04 15:32:04 -070071
zonr6315f762010-10-05 15:35:14 +080072 // TODO(zonr): some check on variable
Shih-wei Liao462aefd2010-06-04 15:32:04 -070073
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070074 RSExportType *ET = RSExportType::CreateFromDecl(this, VD);
75 if (!ET)
76 return false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070077
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070078 RSExportVar *EV = new RSExportVar(this, VD, ET);
79 if (EV == NULL)
80 return false;
81 else
82 mExportVars.push_back(EV);
Shih-wei Liao462aefd2010-06-04 15:32:04 -070083
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070084 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070085}
86
zonr6315f762010-10-05 15:35:14 +080087bool RSContext::processExportFunc(const clang::FunctionDecl *FD) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070088 assert(!FD->getName().empty() && "Function name should not be empty");
Shih-wei Liao537446c2010-06-11 16:05:55 -070089
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070090 if (!FD->isThisDeclarationADefinition())
91 return false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070092
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070093 if (FD->getStorageClass() != clang::SC_None) {
94 fprintf(stderr, "RSContext::processExportFunc : cannot export extern or "
95 "static function '%s'\n", FD->getName().str().c_str());
96 return false;
97 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -070098
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070099 RSExportFunc *EF = RSExportFunc::Create(this, FD);
100 if (EF == NULL)
101 return false;
102 else
103 mExportFuncs.push_back(EF);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700104
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700105 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700106}
107
108
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700109bool RSContext::processExportType(const llvm::StringRef &Name) {
110 clang::TranslationUnitDecl *TUDecl = mCtx->getTranslationUnitDecl();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700111
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700112 assert(TUDecl != NULL && "Translation unit declaration (top-level "
113 "declaration) is null object");
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700114
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700115 const clang::IdentifierInfo *II = mPP->getIdentifierInfo(Name);
116 if (II == NULL)
zonr6315f762010-10-05 15:35:14 +0800117 // TODO(zonr): alert identifier @Name mark as an exportable type cannot be
118 // found
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700119 return false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700120
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700121 clang::DeclContext::lookup_const_result R = TUDecl->lookup(II);
122 RSExportType *ET = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700123
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700124 RSExportPointerType::IntegerType = mCtx->IntTy.getTypePtr();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700125
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700126 for (clang::DeclContext::lookup_const_iterator I = R.first, E = R.second;
127 I != E;
128 I++) {
129 clang::NamedDecl *const ND = *I;
130 const clang::Type *T = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700131
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700132 switch (ND->getKind()) {
133 case clang::Decl::Typedef: {
134 T = static_cast<const clang::TypedefDecl*>(
135 ND)->getCanonicalDecl()->getUnderlyingType().getTypePtr();
136 break;
137 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700138 case clang::Decl::Record: {
139 T = static_cast<const clang::RecordDecl*>(ND)->getTypeForDecl();
140 break;
141 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700142 default: {
143 // unsupported, skip
144 break;
Shih-wei Liaoac918152010-08-29 02:43:24 -0700145 }
146 }
Shih-wei Liao537446c2010-06-11 16:05:55 -0700147
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700148 if (T != NULL)
149 ET = RSExportType::Create(this, T);
150 }
151
152 RSExportPointerType::IntegerType = NULL;
153
154 return (ET != NULL);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700155}
156
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700157void RSContext::processExport() {
158 if (mNeedExportVars.empty() &&
159 mNeedExportFuncs.empty() &&
160 !mExportAllNonStaticVars && !mExportAllNonStaticFuncs) {
161 fprintf(stderr, "note: No reflection because there are no #pragma "
162 "rs export_var(...), #pragma rs export_func(...), "
zonr6315f762010-10-05 15:35:14 +0800163 "#pragma rs export_var_all, or #pragma rs "
164 "export_func_all\n");
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700165 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700166
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700167 // Export variable
168 clang::TranslationUnitDecl *TUDecl = mCtx->getTranslationUnitDecl();
169 for (clang::DeclContext::decl_iterator DI = TUDecl->decls_begin(),
170 DE = TUDecl->decls_end();
171 DI != TUDecl->decls_end();
172 DI++) {
173 if (DI->getKind() == clang::Decl::Var) {
174 clang::VarDecl *VD = (clang::VarDecl*) (*DI);
175 if (mExportAllNonStaticVars &&
176 (VD->getLinkage() == clang::ExternalLinkage)) {
177 if (!processExportVar(VD)) {
178 fprintf(stderr, "RSContext::processExport : failed to export var "
179 "'%s'\n", VD->getNameAsString().c_str());
Ying Wang3f8b44d2010-09-04 01:17:01 -0700180 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700181 } else {
182 NeedExportVarSet::iterator EI = mNeedExportVars.find(VD->getName());
183 if (EI != mNeedExportVars.end() && processExportVar(VD)) {
184 mNeedExportVars.erase(EI);
185 }
186 }
187 } else if (DI->getKind() == clang::Decl::Function) {
188 // Export functions
189 clang::FunctionDecl *FD = (clang::FunctionDecl*) (*DI);
190 if (mExportAllNonStaticFuncs &&
191 (FD->getLinkage() == clang::ExternalLinkage)) {
192 if (!processExportFunc(FD)) {
193 fprintf(stderr, "RSContext::processExport : failed to export func "
194 "'%s'\n", FD->getNameAsString().c_str());
195 }
196 } else {
197 NeedExportFuncSet::iterator EI = mNeedExportFuncs.find(FD->getName());
198 if (EI != mNeedExportFuncs.end() && processExportFunc(FD))
199 mNeedExportFuncs.erase(EI);
200 }
Ying Wang3f8b44d2010-09-04 01:17:01 -0700201 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700202 }
Ying Wang3f8b44d2010-09-04 01:17:01 -0700203
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700204 // Finally, export type forcely set to be exported by user
205 for (NeedExportTypeSet::const_iterator EI = mNeedExportTypes.begin(),
206 EE = mNeedExportTypes.end();
207 EI != EE;
208 EI++) {
209 if (!processExportType(EI->getKey())) {
210 fprintf(stderr, "RSContext::processExport : failed to export type "
211 "'%s'\n", EI->getKey().str().c_str());
Ying Wang3f8b44d2010-09-04 01:17:01 -0700212 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700213 }
Shih-wei Liao537446c2010-06-11 16:05:55 -0700214
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700215 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700216}
217
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700218bool RSContext::insertExportType(const llvm::StringRef &TypeName,
219 RSExportType *ET) {
220 ExportTypeMap::value_type *NewItem =
221 ExportTypeMap::value_type::Create(TypeName.begin(),
222 TypeName.end(),
223 mExportTypes.getAllocator(),
224 ET);
Shih-wei Liao6de89272010-07-15 15:26:20 -0700225
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700226 if (mExportTypes.insert(NewItem)) {
Shih-wei Liao6de89272010-07-15 15:26:20 -0700227 return true;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700228 } else {
229 free(NewItem);
230 return false;
231 }
232}
233
234bool RSContext::reflectToJava(const char *OutputPackageName,
235 const std::string &InputFileName,
236 const std::string &OutputBCFileName,
237 char realPackageName[],
238 int bSize) {
239 if (realPackageName != NULL) {
240 *realPackageName = 0;
241 }
242
243 if (OutputPackageName == NULL) {
244 if (!mReflectJavaPackageName.empty()) {
245 OutputPackageName = mReflectJavaPackageName.c_str();
246 } else {
247 // no package name, just return
248 return true;
249 }
250 }
251
252 // Copy back the really applied package name
253 if (realPackageName != NULL) {
254 strncpy(realPackageName, OutputPackageName, bSize - 1);
255 }
256
257 RSReflection *R = new RSReflection(this);
258 bool ret = R->reflect(OutputPackageName, InputFileName, OutputBCFileName);
zonr6315f762010-10-05 15:35:14 +0800259 if (!ret)
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700260 fprintf(stderr, "RSContext::reflectToJava : failed to do reflection "
261 "(%s)\n", R->getLastError());
262 delete R;
263 return ret;
264}
265
266bool RSContext::reflectToJavaPath(const char *OutputPathName) {
267 if (OutputPathName == NULL)
268 // no path name, just return
269 return true;
270
271 setReflectJavaPathName(std::string(OutputPathName));
272 return true;
Shih-wei Liao6de89272010-07-15 15:26:20 -0700273}
274
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700275RSContext::~RSContext() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700276 delete mLicenseNote;
277 delete mTargetData;
Zonr Changa41ce1d2010-10-06 02:23:12 +0800278 for (ExportableList::iterator I = mExportables.begin(),
279 E = mExportables.end();
280 I != E;
281 I++) {
282 delete *I;
283 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700284}