blob: f5aeb8910bf14ce8a5f693d6f0057fa6f181ecb2 [file] [log] [blame]
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001#include "slang.hpp"
2#include "slang_rs_context.hpp"
3#include "slang_rs_reflection.hpp"
4#include "slang_rs_export_var.hpp"
5#include "slang_rs_export_func.hpp"
6#include "slang_rs_export_type.hpp"
7#include "slang_rs_pragma_handler.hpp"
8
9#include "clang/AST/Type.h" /* for class clang::QualType */
10#include "clang/AST/Decl.h" /* for class clang::*Decl */
Shih-wei Liao462aefd2010-06-04 15:32:04 -070011#include "clang/AST/DeclBase.h" /* for class clang::Decl and clang::DeclContext */
12#include "clang/AST/ASTContext.h" /* for class clang::ASTContext */
13#include "clang/Basic/TargetInfo.h" /* for class clang::TargetInfo */
Victor Hsiehe3756aa2010-07-12 19:28:22 +080014#include "clang/Basic/Linkage.h" /* for class clang::Linkage */
Shih-wei Liao462aefd2010-06-04 15:32:04 -070015#include "clang/Index/ASTLocation.h" /* for class clang::idx::ASTLocation */
16
17#include "llvm/LLVMContext.h" /* for function llvm::getGlobalContext() */
18#include "llvm/Target/TargetData.h" /* for class llvm::TargetData */
19
20using namespace clang::idx;
21
22namespace slang {
23
Shih-wei Liao001fb6d2010-06-21 11:17:11 -070024RSContext::RSContext(Preprocessor* PP, ASTContext* Ctx, const TargetInfo* Target) :
Shih-wei Liao462aefd2010-06-04 15:32:04 -070025 mPP(PP),
Shih-wei Liao001fb6d2010-06-21 11:17:11 -070026 mCtx(Ctx),
Shih-wei Liao462aefd2010-06-04 15:32:04 -070027 mTarget(Target),
28 mTargetData(NULL),
Victor Hsiehc6718b32010-06-23 09:29:44 +080029 mRSExportVarAllPragma(NULL),
Victor Hsiehc6718b32010-06-23 09:29:44 +080030 mRSExportFuncAllPragma(NULL),
Victor Hsiehd8a0d182010-07-07 19:22:33 +080031 mRSReflectLicensePragma(NULL),
Victor Hsieha5070422010-07-08 09:21:07 +080032 mExportAllNonStaticVars(false),
Shih-wei Liao4c9f7422010-08-05 04:30:02 -070033 mExportAllNonStaticFuncs(false),
Shih-wei Liaof52a6202010-09-10 17:40:53 -070034 mLicenseNote(NULL),
35 mLLVMContext(llvm::getGlobalContext())
Shih-wei Liao462aefd2010-06-04 15:32:04 -070036{
37 /* For #pragma rs export_var */
Shih-wei Liao462aefd2010-06-04 15:32:04 -070038
Victor Hsiehc6718b32010-06-23 09:29:44 +080039 /* For #pragma rs export_var_all */
40 mRSExportVarAllPragma = RSPragmaHandler::CreatePragmaExportVarAllHandler(this);
41 if(mRSExportVarAllPragma != NULL)
42 PP->AddPragmaHandler("rs", mRSExportVarAllPragma);
43
Victor Hsiehc6718b32010-06-23 09:29:44 +080044 /* For #pragma rs export_func_all */
45 mRSExportFuncAllPragma = RSPragmaHandler::CreatePragmaExportFuncAllHandler(this);
46 if(mRSExportFuncAllPragma != NULL)
47 PP->AddPragmaHandler("rs", mRSExportFuncAllPragma);
48
Shih-wei Liaof52a6202010-09-10 17:40:53 -070049 PP->AddPragmaHandler("rs", RSPragmaHandler::CreatePragmaExportVarHandler(this));
50 PP->AddPragmaHandler("rs", RSPragmaHandler::CreatePragmaExportFuncHandler(this));
51 PP->AddPragmaHandler("rs", RSPragmaHandler::CreatePragmaExportTypeHandler(this));
52 PP->AddPragmaHandler("rs", RSPragmaHandler::CreatePragmaJavaPackageNameHandler(this));
Shih-wei Liao537446c2010-06-11 16:05:55 -070053
Victor Hsiehd8a0d182010-07-07 19:22:33 +080054 /* For #pragma rs set_reflect_license */
55 mRSReflectLicensePragma = RSPragmaHandler::RSPragmaHandler::CreatePragmaReflectLicenseHandler(this);
56 if (mRSReflectLicensePragma != NULL)
57 PP->AddPragmaHandler("rs", mRSReflectLicensePragma);
58
Shih-wei Liao001fb6d2010-06-21 11:17:11 -070059 /* Prepare target data */
Shih-wei Liao462aefd2010-06-04 15:32:04 -070060 mTargetData = new llvm::TargetData(Slang::TargetDescription);
61
62 return;
63}
64
65bool RSContext::processExportVar(const VarDecl* VD) {
66 assert(!VD->getName().empty() && "Variable name should not be empty");
67
68 /* TODO: some check on variable */
69
70 RSExportType* ET = RSExportType::CreateFromDecl(this, VD);
Shih-wei Liao537446c2010-06-11 16:05:55 -070071 if(!ET)
Shih-wei Liao462aefd2010-06-04 15:32:04 -070072 return false;
73
74 RSExportVar* EV = new RSExportVar(this, VD, ET);
75 if(EV == NULL)
76 return false;
77 else
78 mExportVars.push_back(EV);
79
80 return true;
81}
82
83bool RSContext::processExportFunc(const FunctionDecl* FD) {
84 assert(!FD->getName().empty() && "Function name should not be empty");
Shih-wei Liao537446c2010-06-11 16:05:55 -070085
Shih-wei Liao462aefd2010-06-04 15:32:04 -070086 if(!FD->isThisDeclarationADefinition())
87 return false;
88
Shih-wei Liaof52a6202010-09-10 17:40:53 -070089 if(FD->getStorageClass() != clang::SC_None) {
Shih-wei Liao462aefd2010-06-04 15:32:04 -070090 printf("RSContext::processExportFunc : cannot export extern or static function '%s'\n", FD->getName().str().c_str());
91 return false;
92 }
93
94 RSExportFunc* EF = RSExportFunc::Create(this, FD);
95 if(EF == NULL)
96 return false;
97 else
98 mExportFuncs.push_back(EF);
99
100 return true;
101}
102
103
Shih-wei Liao001fb6d2010-06-21 11:17:11 -0700104bool RSContext::processExportType(const llvm::StringRef& Name) {
105 TranslationUnitDecl* TUDecl = mCtx->getTranslationUnitDecl();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700106
107 assert(TUDecl != NULL && "Translation unit declaration (top-level declaration) is null object");
108
109 const IdentifierInfo* II = mPP->getIdentifierInfo(Name);
110 if(II == NULL)
111 /* TODO: error: identifier @Name mark as an exportable type cannot be found */
112 return false;
113
114 DeclContext::lookup_const_result R = TUDecl->lookup(II);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700115 RSExportType* ET = NULL;
116
Shih-wei Liao001fb6d2010-06-21 11:17:11 -0700117 RSExportPointerType::IntegerType = mCtx->IntTy.getTypePtr();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700118
119 for(DeclContext::lookup_const_iterator I = R.first;
120 I != R.second;
Shih-wei Liao537446c2010-06-11 16:05:55 -0700121 I++)
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700122 {
123 NamedDecl* const ND = *I;
Shih-wei Liaof52a6202010-09-10 17:40:53 -0700124 const Type* T = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700125
Shih-wei Liaof52a6202010-09-10 17:40:53 -0700126 switch(ND->getKind()) {
127 case Decl::Typedef:
128 T = static_cast<const TypedefDecl*>(ND)->getCanonicalDecl()->getUnderlyingType().getTypePtr();
129 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700130
Shih-wei Liaof52a6202010-09-10 17:40:53 -0700131 case Decl::Record:
132 T = static_cast<const RecordDecl*>(ND)->getTypeForDecl();
133 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700134
Shih-wei Liaof52a6202010-09-10 17:40:53 -0700135 default:
136 /* unsupported, skip */
137 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700138 }
Shih-wei Liaof52a6202010-09-10 17:40:53 -0700139
140 if(T != NULL)
141 ET = RSExportType::Create(this, T);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700142 }
143
144 RSExportPointerType::IntegerType = NULL;
145
146 return (ET != NULL);
147}
148
Shih-wei Liao001fb6d2010-06-21 11:17:11 -0700149void RSContext::processExport() {
Shih-wei Liao28cf66d2010-08-29 03:11:07 -0700150 if (mNeedExportVars.empty() && mNeedExportFuncs.empty() && !mExportAllNonStaticVars && !mExportAllNonStaticFuncs) {
151 printf("note: No reflection because there are no #pragma rs export_var(...), #pragma rs export_func(...), #pragma rs export_var_all, or #pragma rs export_func_all\n");
152 //mExportAllNonStaticVars = true;
153 //mExportAllNonStaticFuncs = true;
Shih-wei Liaoac918152010-08-29 02:43:24 -0700154 }
Shih-wei Liao001fb6d2010-06-21 11:17:11 -0700155 TranslationUnitDecl* TUDecl = mCtx->getTranslationUnitDecl();
Shih-wei Liaoac918152010-08-29 02:43:24 -0700156 for (DeclContext::decl_iterator DI = TUDecl->decls_begin();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700157 DI != TUDecl->decls_end();
Shih-wei Liaoac918152010-08-29 02:43:24 -0700158 DI++) {
Victor Hsiehd8a0d182010-07-07 19:22:33 +0800159 if (DI->getKind() == Decl::Var) {
Shih-wei Liaoac918152010-08-29 02:43:24 -0700160 /* Export variables */
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700161 VarDecl* VD = (VarDecl*) (*DI);
Victor Hsiehe3756aa2010-07-12 19:28:22 +0800162 if (mExportAllNonStaticVars && VD->getLinkage() == ExternalLinkage) {
Victor Hsiehc6718b32010-06-23 09:29:44 +0800163 if (!processExportVar(VD)) {
Shih-wei Liaof52a6202010-09-10 17:40:53 -0700164 printf("RSContext::processExport : failed to export var '%s'\n", VD->getNameAsString().c_str());
Victor Hsiehc6718b32010-06-23 09:29:44 +0800165 }
166 } else {
167 NeedExportVarSet::iterator EI = mNeedExportVars.find(VD->getName());
Shih-wei Liaoac918152010-08-29 02:43:24 -0700168 if (EI != mNeedExportVars.end() && processExportVar(VD)) {
Victor Hsiehc6718b32010-06-23 09:29:44 +0800169 mNeedExportVars.erase(EI);
Shih-wei Liaoac918152010-08-29 02:43:24 -0700170 }
Victor Hsiehc6718b32010-06-23 09:29:44 +0800171 }
Victor Hsiehd8a0d182010-07-07 19:22:33 +0800172 } else if (DI->getKind() == Decl::Function) {
Shih-wei Liaoac918152010-08-29 02:43:24 -0700173 /* Export functions */
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700174 FunctionDecl* FD = (FunctionDecl*) (*DI);
Victor Hsiehe3756aa2010-07-12 19:28:22 +0800175 if (mExportAllNonStaticFuncs && FD->getLinkage() == ExternalLinkage) {
Victor Hsiehc6718b32010-06-23 09:29:44 +0800176 if (!processExportFunc(FD)) {
Shih-wei Liaof52a6202010-09-10 17:40:53 -0700177 printf("RSContext::processExport : failed to export func '%s'\n", FD->getNameAsString().c_str());
Victor Hsiehc6718b32010-06-23 09:29:44 +0800178 }
179 } else {
180 NeedExportFuncSet::iterator EI = mNeedExportFuncs.find(FD->getName());
Shih-wei Liaoac918152010-08-29 02:43:24 -0700181 if (EI != mNeedExportFuncs.end() && processExportFunc(FD))
Victor Hsiehc6718b32010-06-23 09:29:44 +0800182 mNeedExportFuncs.erase(EI);
183 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700184 }
185 }
186
187 /* Finally, export type forcely set to be exported by user */
Shih-wei Liaoac918152010-08-29 02:43:24 -0700188 for (NeedExportTypeSet::const_iterator EI = mNeedExportTypes.begin();
189 EI != mNeedExportTypes.end();
190 EI++) {
191 if (!processExportType(EI->getKey())) {
192 printf("RSContext::processExport : failed to export type '%s'\n", EI->getKey().str().c_str());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700193
Shih-wei Liaoac918152010-08-29 02:43:24 -0700194 }
195 }
Shih-wei Liao537446c2010-06-11 16:05:55 -0700196
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700197 return;
198}
199
200bool RSContext::insertExportType(const llvm::StringRef& TypeName, RSExportType* ET) {
201 ExportTypeMap::value_type* NewItem = ExportTypeMap::value_type::Create(TypeName.begin(), TypeName.end(), mExportTypes.getAllocator(), ET);
202
203 if(mExportTypes.insert(NewItem)) {
204 return true;
205 } else {
Shih-wei Liaoc81dd702010-08-20 04:58:32 -0700206 free(NewItem);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700207 return false;
208 }
209}
210
Ying Wang3f8b44d2010-09-04 01:17:01 -0700211bool RSContext::reflectToJava(const char* OutputPackageName, const std::string& InputFileName, const std::string& OutputBCFileName, char realPackageName[], int bSize) {
212 if (realPackageName != NULL) {
213 *realPackageName = 0;
214 }
215
216 if(OutputPackageName == NULL) {
217 if(!mReflectJavaPackageName.empty()) {
Shih-wei Liao537446c2010-06-11 16:05:55 -0700218 OutputPackageName = mReflectJavaPackageName.c_str();
Ying Wang3f8b44d2010-09-04 01:17:01 -0700219 } else {
Shih-wei Liao537446c2010-06-11 16:05:55 -0700220 return true; /* no package name, just return */
Ying Wang3f8b44d2010-09-04 01:17:01 -0700221 }
222 }
223
224 // Copy back the really applied package name
225 if (realPackageName != NULL) {
226 strncpy(realPackageName, OutputPackageName, bSize - 1);
227 }
Shih-wei Liao537446c2010-06-11 16:05:55 -0700228
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700229 RSReflection* R = new RSReflection(this);
Shih-wei Liao537446c2010-06-11 16:05:55 -0700230 bool ret = R->reflect(OutputPackageName, InputFileName, OutputBCFileName);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700231 if(!ret)
232 printf("RSContext::reflectToJava : failed to do reflection (%s)\n", R->getLastError());
233 delete R;
234 return ret;
235}
236
Shih-wei Liao6de89272010-07-15 15:26:20 -0700237bool RSContext::reflectToJavaPath(const char* OutputPathName) {
238 if(OutputPathName == NULL)
239 return true; /* no path name, just return */
240
241 setReflectJavaPathName(std::string(OutputPathName));
242 return true;
243}
244
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700245RSContext::~RSContext() {
Shih-wei Liaof83d3c32010-07-30 22:22:49 -0700246 /* delete mRSExportVarPragma; // These are deleted by mPP.reset() that was invoked at the end of Slang::compile(). Doing it again in ~RSContext here will cause seg-faults
Shih-wei Liao537446c2010-06-11 16:05:55 -0700247 delete mRSExportFuncPragma;
248 delete mRSExportTypePragma;
249 delete mRSJavaPackageNamePragma;
Victor Hsiehd8a0d182010-07-07 19:22:33 +0800250 delete mRSReflectLicensePragma;
Shih-wei Liaof83d3c32010-07-30 22:22:49 -0700251 */
Victor Hsiehd8a0d182010-07-07 19:22:33 +0800252 delete mLicenseNote;
Shih-wei Liao537446c2010-06-11 16:05:55 -0700253 delete mTargetData;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700254}
255
256} /* namespace slang */