blob: 7181e7c8159682b6f8afd6ae5ba48e116f66cda0 [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 */
11#include "clang/Index/Utils.h" /* for class clang::idx::ResolveLocationInAST() */
12#include "clang/AST/DeclBase.h" /* for class clang::Decl and clang::DeclContext */
13#include "clang/AST/ASTContext.h" /* for class clang::ASTContext */
14#include "clang/Basic/TargetInfo.h" /* for class clang::TargetInfo */
Victor Hsiehe3756aa2010-07-12 19:28:22 +080015#include "clang/Basic/Linkage.h" /* for class clang::Linkage */
Shih-wei Liao462aefd2010-06-04 15:32:04 -070016#include "clang/Index/ASTLocation.h" /* for class clang::idx::ASTLocation */
17
18#include "llvm/LLVMContext.h" /* for function llvm::getGlobalContext() */
19#include "llvm/Target/TargetData.h" /* for class llvm::TargetData */
20
21using namespace clang::idx;
22
23namespace slang {
24
Shih-wei Liao001fb6d2010-06-21 11:17:11 -070025RSContext::RSContext(Preprocessor* PP, ASTContext* Ctx, const TargetInfo* Target) :
Shih-wei Liao462aefd2010-06-04 15:32:04 -070026 mPP(PP),
Shih-wei Liao001fb6d2010-06-21 11:17:11 -070027 mCtx(Ctx),
Shih-wei Liao462aefd2010-06-04 15:32:04 -070028 mTarget(Target),
29 mTargetData(NULL),
30 mLLVMContext(llvm::getGlobalContext()),
31 mRSExportVarPragma(NULL),
Victor Hsiehc6718b32010-06-23 09:29:44 +080032 mRSExportVarAllPragma(NULL),
Shih-wei Liao462aefd2010-06-04 15:32:04 -070033 mRSExportFuncPragma(NULL),
Victor Hsiehc6718b32010-06-23 09:29:44 +080034 mRSExportFuncAllPragma(NULL),
Shih-wei Liao537446c2010-06-11 16:05:55 -070035 mRSExportTypePragma(NULL),
Victor Hsiehc6718b32010-06-23 09:29:44 +080036 mRSJavaPackageNamePragma(NULL),
Victor Hsiehd8a0d182010-07-07 19:22:33 +080037 mRSReflectLicensePragma(NULL),
Victor Hsieha5070422010-07-08 09:21:07 +080038 mExportAllNonStaticVars(false),
39 mExportAllNonStaticFuncs(false)
Shih-wei Liao462aefd2010-06-04 15:32:04 -070040{
41 /* For #pragma rs export_var */
42 mRSExportVarPragma = RSPragmaHandler::CreatePragmaExportVarHandler(this);
43 if(mRSExportVarPragma != NULL)
44 PP->AddPragmaHandler("rs", mRSExportVarPragma);
45
Victor Hsiehc6718b32010-06-23 09:29:44 +080046 /* For #pragma rs export_var_all */
47 mRSExportVarAllPragma = RSPragmaHandler::CreatePragmaExportVarAllHandler(this);
48 if(mRSExportVarAllPragma != NULL)
49 PP->AddPragmaHandler("rs", mRSExportVarAllPragma);
50
Shih-wei Liao462aefd2010-06-04 15:32:04 -070051 /* For #pragma rs export_func */
52 mRSExportFuncPragma = RSPragmaHandler::CreatePragmaExportFuncHandler(this);
53 if(mRSExportFuncPragma != NULL)
54 PP->AddPragmaHandler("rs", mRSExportFuncPragma);
55
Victor Hsiehc6718b32010-06-23 09:29:44 +080056 /* For #pragma rs export_func_all */
57 mRSExportFuncAllPragma = RSPragmaHandler::CreatePragmaExportFuncAllHandler(this);
58 if(mRSExportFuncAllPragma != NULL)
59 PP->AddPragmaHandler("rs", mRSExportFuncAllPragma);
60
Shih-wei Liao462aefd2010-06-04 15:32:04 -070061 /* For #pragma rs export_type */
62 mRSExportTypePragma = RSPragmaHandler::CreatePragmaExportTypeHandler(this);
63 if(mRSExportTypePragma != NULL)
64 PP->AddPragmaHandler("rs", mRSExportTypePragma);
65
Shih-wei Liao537446c2010-06-11 16:05:55 -070066 /* For #pragma rs java_package_name */
67 mRSJavaPackageNamePragma = RSPragmaHandler::CreatePragmaJavaPackageNameHandler(this);
68 if(mRSJavaPackageNamePragma != NULL)
69 PP->AddPragmaHandler("rs", mRSJavaPackageNamePragma);
70
Victor Hsiehd8a0d182010-07-07 19:22:33 +080071 /* For #pragma rs set_reflect_license */
72 mRSReflectLicensePragma = RSPragmaHandler::RSPragmaHandler::CreatePragmaReflectLicenseHandler(this);
73 if (mRSReflectLicensePragma != NULL)
74 PP->AddPragmaHandler("rs", mRSReflectLicensePragma);
75
Shih-wei Liao001fb6d2010-06-21 11:17:11 -070076 /* Prepare target data */
Shih-wei Liao462aefd2010-06-04 15:32:04 -070077 mTargetData = new llvm::TargetData(Slang::TargetDescription);
78
79 return;
80}
81
82bool RSContext::processExportVar(const VarDecl* VD) {
83 assert(!VD->getName().empty() && "Variable name should not be empty");
84
85 /* TODO: some check on variable */
86
87 RSExportType* ET = RSExportType::CreateFromDecl(this, VD);
Shih-wei Liao537446c2010-06-11 16:05:55 -070088 if(!ET)
Shih-wei Liao462aefd2010-06-04 15:32:04 -070089 return false;
90
91 RSExportVar* EV = new RSExportVar(this, VD, ET);
92 if(EV == NULL)
93 return false;
94 else
95 mExportVars.push_back(EV);
96
97 return true;
98}
99
100bool RSContext::processExportFunc(const FunctionDecl* FD) {
101 assert(!FD->getName().empty() && "Function name should not be empty");
Shih-wei Liao537446c2010-06-11 16:05:55 -0700102
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700103 if(!FD->isThisDeclarationADefinition())
104 return false;
105
106 if(FD->getStorageClass() != FunctionDecl::None) {
107 printf("RSContext::processExportFunc : cannot export extern or static function '%s'\n", FD->getName().str().c_str());
108 return false;
109 }
110
111 RSExportFunc* EF = RSExportFunc::Create(this, FD);
112 if(EF == NULL)
113 return false;
114 else
115 mExportFuncs.push_back(EF);
116
117 return true;
118}
119
120
Shih-wei Liao001fb6d2010-06-21 11:17:11 -0700121bool RSContext::processExportType(const llvm::StringRef& Name) {
122 TranslationUnitDecl* TUDecl = mCtx->getTranslationUnitDecl();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700123
124 assert(TUDecl != NULL && "Translation unit declaration (top-level declaration) is null object");
125
126 const IdentifierInfo* II = mPP->getIdentifierInfo(Name);
127 if(II == NULL)
128 /* TODO: error: identifier @Name mark as an exportable type cannot be found */
129 return false;
130
131 DeclContext::lookup_const_result R = TUDecl->lookup(II);
132 bool Done = false;
133 RSExportType* ET = NULL;
134
Shih-wei Liao001fb6d2010-06-21 11:17:11 -0700135 RSExportPointerType::IntegerType = mCtx->IntTy.getTypePtr();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700136
137 for(DeclContext::lookup_const_iterator I = R.first;
138 I != R.second;
Shih-wei Liao537446c2010-06-11 16:05:55 -0700139 I++)
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700140 {
141 NamedDecl* const ND = *I;
142 ASTLocation* LastLoc = new ASTLocation(ND);
Shih-wei Liao001fb6d2010-06-21 11:17:11 -0700143 ASTLocation AL = ResolveLocationInAST(*mCtx, ND->getLocStart(), LastLoc);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700144
145 delete LastLoc;
146 if(AL.isDecl()) {
147 Decl* D = AL.dyn_AsDecl();
148 const Type* T = NULL;
149
150 switch(D->getKind()) {
151 case Decl::Typedef:
152 T = static_cast<const TypedefDecl*>(D)->getCanonicalDecl()->getUnderlyingType().getTypePtr();
153 break;
154
155 case Decl::Record:
156 T = static_cast<const RecordDecl*>(D)->getTypeForDecl();
157 break;
158
159 default:
160 /* unsupported, skip */
161 break;
162 }
163
164 if(T != NULL)
165 ET = RSExportType::Create(this, T);
166 }
167 }
168
169 RSExportPointerType::IntegerType = NULL;
170
171 return (ET != NULL);
172}
173
Shih-wei Liao001fb6d2010-06-21 11:17:11 -0700174void RSContext::processExport() {
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700175 /* Export variable */
Shih-wei Liao001fb6d2010-06-21 11:17:11 -0700176 TranslationUnitDecl* TUDecl = mCtx->getTranslationUnitDecl();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700177 for(DeclContext::decl_iterator DI = TUDecl->decls_begin();
178 DI != TUDecl->decls_end();
179 DI++)
180 {
Victor Hsiehd8a0d182010-07-07 19:22:33 +0800181 if (DI->getKind() == Decl::Var) {
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700182 VarDecl* VD = (VarDecl*) (*DI);
Victor Hsiehe3756aa2010-07-12 19:28:22 +0800183 if (mExportAllNonStaticVars && VD->getLinkage() == ExternalLinkage) {
Victor Hsiehc6718b32010-06-23 09:29:44 +0800184 if (!processExportVar(VD)) {
Victor Hsiehd8a0d182010-07-07 19:22:33 +0800185 printf("RSContext::processExport : failed to export var '%s'\n", VD->getNameAsCString());
Victor Hsiehc6718b32010-06-23 09:29:44 +0800186 }
187 } else {
188 NeedExportVarSet::iterator EI = mNeedExportVars.find(VD->getName());
189 if(EI != mNeedExportVars.end() && processExportVar(VD))
190 mNeedExportVars.erase(EI);
191 }
Victor Hsiehd8a0d182010-07-07 19:22:33 +0800192 } else if (DI->getKind() == Decl::Function) {
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700193 FunctionDecl* FD = (FunctionDecl*) (*DI);
Victor Hsiehe3756aa2010-07-12 19:28:22 +0800194 if (mExportAllNonStaticFuncs && FD->getLinkage() == ExternalLinkage) {
Victor Hsiehc6718b32010-06-23 09:29:44 +0800195 if (!processExportFunc(FD)) {
Victor Hsiehd8a0d182010-07-07 19:22:33 +0800196 printf("RSContext::processExport : failed to export func '%s'\n", FD->getNameAsCString());
Victor Hsiehc6718b32010-06-23 09:29:44 +0800197 }
198 } else {
199 NeedExportFuncSet::iterator EI = mNeedExportFuncs.find(FD->getName());
200 if(EI != mNeedExportFuncs.end() && processExportFunc(FD))
201 mNeedExportFuncs.erase(EI);
202 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700203 }
204 }
205
206 /* Finally, export type forcely set to be exported by user */
207 for(NeedExportTypeSet::const_iterator EI = mNeedExportTypes.begin();
208 EI != mNeedExportTypes.end();
209 EI++)
Shih-wei Liao001fb6d2010-06-21 11:17:11 -0700210 if(!processExportType(EI->getKey()))
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700211 printf("RSContext::processExport : failed to export type '%s'\n", EI->getKey().str().c_str());
212
Shih-wei Liao537446c2010-06-11 16:05:55 -0700213
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700214 return;
215}
216
217bool RSContext::insertExportType(const llvm::StringRef& TypeName, RSExportType* ET) {
218 ExportTypeMap::value_type* NewItem = ExportTypeMap::value_type::Create(TypeName.begin(), TypeName.end(), mExportTypes.getAllocator(), ET);
219
220 if(mExportTypes.insert(NewItem)) {
221 return true;
222 } else {
223 delete NewItem;
224 return false;
225 }
226}
227
Shih-wei Liao537446c2010-06-11 16:05:55 -0700228bool RSContext::reflectToJava(const char* OutputPackageName, const std::string& InputFileName, const std::string& OutputBCFileName) {
229 if(OutputPackageName == NULL)
230 if(!mReflectJavaPackageName.empty())
231 OutputPackageName = mReflectJavaPackageName.c_str();
232 else
233 return true; /* no package name, just return */
234
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700235 RSReflection* R = new RSReflection(this);
Shih-wei Liao537446c2010-06-11 16:05:55 -0700236 bool ret = R->reflect(OutputPackageName, InputFileName, OutputBCFileName);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700237 if(!ret)
238 printf("RSContext::reflectToJava : failed to do reflection (%s)\n", R->getLastError());
239 delete R;
240 return ret;
241}
242
Shih-wei Liao6de89272010-07-15 15:26:20 -0700243bool RSContext::reflectToJavaPath(const char* OutputPathName) {
244 if(OutputPathName == NULL)
245 return true; /* no path name, just return */
246
247 setReflectJavaPathName(std::string(OutputPathName));
248 return true;
249}
250
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700251RSContext::~RSContext() {
Shih-wei Liao537446c2010-06-11 16:05:55 -0700252 delete mRSExportVarPragma;
253 delete mRSExportFuncPragma;
254 delete mRSExportTypePragma;
255 delete mRSJavaPackageNamePragma;
Victor Hsiehd8a0d182010-07-07 19:22:33 +0800256 delete mRSReflectLicensePragma;
Shih-wei Liao537446c2010-06-11 16:05:55 -0700257
Victor Hsiehd8a0d182010-07-07 19:22:33 +0800258 delete mLicenseNote;
Shih-wei Liao537446c2010-06-11 16:05:55 -0700259 delete mTargetData;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700260}
261
262} /* namespace slang */