slang_rs_context.cpp revision 28cf66d9a9f82dc4bd4708db905423d14e101ed6
1#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 */
15#include "clang/Basic/Linkage.h"        /* for class clang::Linkage */
16#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
25RSContext::RSContext(Preprocessor* PP, ASTContext* Ctx, const TargetInfo* Target) :
26    mPP(PP),
27    mCtx(Ctx),
28    mTarget(Target),
29    mTargetData(NULL),
30    mLLVMContext(llvm::getGlobalContext()),
31    mRSExportVarPragma(NULL),
32    mRSExportVarAllPragma(NULL),
33    mRSExportFuncPragma(NULL),
34    mRSExportFuncAllPragma(NULL),
35    mRSExportTypePragma(NULL),
36    mRSJavaPackageNamePragma(NULL),
37    mRSReflectLicensePragma(NULL),
38    mExportAllNonStaticVars(false),
39    mExportAllNonStaticFuncs(false),
40    mLicenseNote(NULL)
41{
42    /* For #pragma rs export_var */
43    mRSExportVarPragma = RSPragmaHandler::CreatePragmaExportVarHandler(this);
44    if(mRSExportVarPragma != NULL)
45        PP->AddPragmaHandler("rs", mRSExportVarPragma);
46
47    /* For #pragma rs export_var_all */
48    mRSExportVarAllPragma = RSPragmaHandler::CreatePragmaExportVarAllHandler(this);
49    if(mRSExportVarAllPragma != NULL)
50        PP->AddPragmaHandler("rs", mRSExportVarAllPragma);
51
52    /* For #pragma rs export_func */
53    mRSExportFuncPragma = RSPragmaHandler::CreatePragmaExportFuncHandler(this);
54    if(mRSExportFuncPragma != NULL)
55        PP->AddPragmaHandler("rs", mRSExportFuncPragma);
56
57    /* For #pragma rs export_func_all */
58    mRSExportFuncAllPragma = RSPragmaHandler::CreatePragmaExportFuncAllHandler(this);
59    if(mRSExportFuncAllPragma != NULL)
60        PP->AddPragmaHandler("rs", mRSExportFuncAllPragma);
61
62    /* For #pragma rs export_type */
63    mRSExportTypePragma = RSPragmaHandler::CreatePragmaExportTypeHandler(this);
64    if(mRSExportTypePragma != NULL)
65        PP->AddPragmaHandler("rs", mRSExportTypePragma);
66
67    /* For #pragma rs java_package_name */
68    mRSJavaPackageNamePragma = RSPragmaHandler::CreatePragmaJavaPackageNameHandler(this);
69    if(mRSJavaPackageNamePragma != NULL)
70        PP->AddPragmaHandler("rs", mRSJavaPackageNamePragma);
71
72    /* For #pragma rs set_reflect_license */
73    mRSReflectLicensePragma = RSPragmaHandler::RSPragmaHandler::CreatePragmaReflectLicenseHandler(this);
74    if (mRSReflectLicensePragma != NULL)
75        PP->AddPragmaHandler("rs", mRSReflectLicensePragma);
76
77    /* Prepare target data */
78    mTargetData = new llvm::TargetData(Slang::TargetDescription);
79
80    return;
81}
82
83bool RSContext::processExportVar(const VarDecl* VD) {
84    assert(!VD->getName().empty() && "Variable name should not be empty");
85
86    /* TODO: some check on variable */
87
88    RSExportType* ET = RSExportType::CreateFromDecl(this, VD);
89    if(!ET)
90        return false;
91
92    RSExportVar* EV = new RSExportVar(this, VD, ET);
93    if(EV == NULL)
94        return false;
95    else
96        mExportVars.push_back(EV);
97
98    return true;
99}
100
101bool RSContext::processExportFunc(const FunctionDecl* FD) {
102    assert(!FD->getName().empty() && "Function name should not be empty");
103
104    if(!FD->isThisDeclarationADefinition())
105        return false;
106
107    if(FD->getStorageClass() != FunctionDecl::None) {
108        printf("RSContext::processExportFunc : cannot export extern or static function '%s'\n", FD->getName().str().c_str());
109        return false;
110    }
111
112    RSExportFunc* EF = RSExportFunc::Create(this, FD);
113    if(EF == NULL)
114        return false;
115    else
116        mExportFuncs.push_back(EF);
117
118    return true;
119}
120
121
122bool RSContext::processExportType(const llvm::StringRef& Name) {
123    TranslationUnitDecl* TUDecl = mCtx->getTranslationUnitDecl();
124
125    assert(TUDecl != NULL && "Translation unit declaration (top-level declaration) is null object");
126
127    const IdentifierInfo* II = mPP->getIdentifierInfo(Name);
128    if(II == NULL)
129        /* TODO: error: identifier @Name mark as an exportable type cannot be found */
130        return false;
131
132    DeclContext::lookup_const_result R = TUDecl->lookup(II);
133    bool Done = false;
134    RSExportType* ET = NULL;
135
136    RSExportPointerType::IntegerType = mCtx->IntTy.getTypePtr();
137
138    for(DeclContext::lookup_const_iterator I = R.first;
139        I != R.second;
140        I++)
141    {
142        NamedDecl* const ND = *I;
143        ASTLocation* LastLoc = new ASTLocation(ND);
144        ASTLocation AL = ResolveLocationInAST(*mCtx, ND->getLocStart(), LastLoc);
145
146        delete LastLoc;
147        if(AL.isDecl()) {
148            Decl* D = AL.dyn_AsDecl();
149            const Type* T = NULL;
150
151            switch(D->getKind()) {
152                case Decl::Typedef:
153                    T = static_cast<const TypedefDecl*>(D)->getCanonicalDecl()->getUnderlyingType().getTypePtr();
154                break;
155
156                case Decl::Record:
157                    T = static_cast<const RecordDecl*>(D)->getTypeForDecl();
158                break;
159
160                default:
161                    /* unsupported, skip */
162                break;
163            }
164
165            if(T != NULL)
166                ET = RSExportType::Create(this, T);
167        }
168    }
169
170    RSExportPointerType::IntegerType = NULL;
171
172    return (ET != NULL);
173}
174
175void RSContext::processExport() {
176    if (mNeedExportVars.empty() && mNeedExportFuncs.empty() && !mExportAllNonStaticVars && !mExportAllNonStaticFuncs) {
177        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");
178        //mExportAllNonStaticVars = true;
179        //mExportAllNonStaticFuncs = true;
180    }
181    TranslationUnitDecl* TUDecl = mCtx->getTranslationUnitDecl();
182    for (DeclContext::decl_iterator DI = TUDecl->decls_begin();
183        DI != TUDecl->decls_end();
184        DI++) {
185        if (DI->getKind() == Decl::Var) {
186            /* Export variables */
187            VarDecl* VD = (VarDecl*) (*DI);
188            if (mExportAllNonStaticVars && VD->getLinkage() == ExternalLinkage) {
189                if (!processExportVar(VD)) {
190                    printf("RSContext::processExport : failed to export var '%s'\n", VD->getNameAsCString());
191                }
192            } else {
193                NeedExportVarSet::iterator EI = mNeedExportVars.find(VD->getName());
194                if (EI != mNeedExportVars.end() && processExportVar(VD)) {
195                    mNeedExportVars.erase(EI);
196                }
197            }
198        } else if (DI->getKind() == Decl::Function) {
199            /* Export functions */
200            FunctionDecl* FD = (FunctionDecl*) (*DI);
201            if (mExportAllNonStaticFuncs && FD->getLinkage() == ExternalLinkage) {
202                if (!processExportFunc(FD)) {
203                    printf("RSContext::processExport : failed to export func '%s'\n", FD->getNameAsCString());
204                }
205            } else {
206                NeedExportFuncSet::iterator EI = mNeedExportFuncs.find(FD->getName());
207                if (EI != mNeedExportFuncs.end() && processExportFunc(FD))
208                    mNeedExportFuncs.erase(EI);
209            }
210        }
211    }
212
213    /* Finally, export type forcely set to be exported by user */
214    for (NeedExportTypeSet::const_iterator EI = mNeedExportTypes.begin();
215         EI != mNeedExportTypes.end();
216         EI++) {
217      if (!processExportType(EI->getKey())) {
218        printf("RSContext::processExport : failed to export type '%s'\n", EI->getKey().str().c_str());
219
220      }
221    }
222
223    return;
224}
225
226bool RSContext::insertExportType(const llvm::StringRef& TypeName, RSExportType* ET) {
227    ExportTypeMap::value_type* NewItem = ExportTypeMap::value_type::Create(TypeName.begin(), TypeName.end(), mExportTypes.getAllocator(), ET);
228
229    if(mExportTypes.insert(NewItem)) {
230        return true;
231    } else {
232        free(NewItem);
233        return false;
234    }
235}
236
237bool RSContext::reflectToJava(const char* OutputPackageName, const std::string& InputFileName, const std::string& OutputBCFileName) {
238    if(OutputPackageName == NULL)
239        if(!mReflectJavaPackageName.empty())
240            OutputPackageName = mReflectJavaPackageName.c_str();
241        else
242            return true; /* no package name, just return */
243
244    RSReflection* R = new RSReflection(this);
245    bool ret = R->reflect(OutputPackageName, InputFileName, OutputBCFileName);
246    if(!ret)
247        printf("RSContext::reflectToJava : failed to do reflection (%s)\n", R->getLastError());
248    delete R;
249    return ret;
250}
251
252bool RSContext::reflectToJavaPath(const char* OutputPathName) {
253    if(OutputPathName == NULL)
254        return true; /* no path name, just return */
255
256    setReflectJavaPathName(std::string(OutputPathName));
257    return true;
258}
259
260RSContext::~RSContext() {
261  /*    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
262    delete mRSExportFuncPragma;
263    delete mRSExportTypePragma;
264    delete mRSJavaPackageNamePragma;
265    delete mRSReflectLicensePragma;
266  */
267    delete mLicenseNote;
268    delete mTargetData;
269}
270
271}   /* namespace slang */
272