slang_rs_context.cpp revision c81dd70ab201ba13033004d36107ed96a6ad8036
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    /* Export variable */
177    TranslationUnitDecl* TUDecl = mCtx->getTranslationUnitDecl();
178    for(DeclContext::decl_iterator DI = TUDecl->decls_begin();
179        DI != TUDecl->decls_end();
180        DI++)
181    {
182        if (DI->getKind() == Decl::Var) {
183            VarDecl* VD = (VarDecl*) (*DI);
184            if (mExportAllNonStaticVars && VD->getLinkage() == ExternalLinkage) {
185                if (!processExportVar(VD)) {
186                    printf("RSContext::processExport : failed to export var '%s'\n", VD->getNameAsCString());
187                }
188            } else {
189                NeedExportVarSet::iterator EI = mNeedExportVars.find(VD->getName());
190                if(EI != mNeedExportVars.end() && processExportVar(VD))
191                    mNeedExportVars.erase(EI);
192            }
193        } else if (DI->getKind() == Decl::Function) {
194            FunctionDecl* FD = (FunctionDecl*) (*DI);
195            if (mExportAllNonStaticFuncs && FD->getLinkage() == ExternalLinkage) {
196                if (!processExportFunc(FD)) {
197                    printf("RSContext::processExport : failed to export func '%s'\n", FD->getNameAsCString());
198                }
199            } else {
200                NeedExportFuncSet::iterator EI = mNeedExportFuncs.find(FD->getName());
201                if(EI != mNeedExportFuncs.end() && processExportFunc(FD))
202                    mNeedExportFuncs.erase(EI);
203            }
204        }
205    }
206
207    /* Finally, export type forcely set to be exported by user */
208    for(NeedExportTypeSet::const_iterator EI = mNeedExportTypes.begin();
209        EI != mNeedExportTypes.end();
210        EI++)
211        if(!processExportType(EI->getKey()))
212            printf("RSContext::processExport : failed to export type '%s'\n", EI->getKey().str().c_str());
213
214
215    return;
216}
217
218bool RSContext::insertExportType(const llvm::StringRef& TypeName, RSExportType* ET) {
219    ExportTypeMap::value_type* NewItem = ExportTypeMap::value_type::Create(TypeName.begin(), TypeName.end(), mExportTypes.getAllocator(), ET);
220
221    if(mExportTypes.insert(NewItem)) {
222        return true;
223    } else {
224        free(NewItem);
225        return false;
226    }
227}
228
229bool RSContext::reflectToJava(const char* OutputPackageName, const std::string& InputFileName, const std::string& OutputBCFileName) {
230    if(OutputPackageName == NULL)
231        if(!mReflectJavaPackageName.empty())
232            OutputPackageName = mReflectJavaPackageName.c_str();
233        else
234            return true; /* no package name, just return */
235
236    RSReflection* R = new RSReflection(this);
237    bool ret = R->reflect(OutputPackageName, InputFileName, OutputBCFileName);
238    if(!ret)
239        printf("RSContext::reflectToJava : failed to do reflection (%s)\n", R->getLastError());
240    delete R;
241    return ret;
242}
243
244bool RSContext::reflectToJavaPath(const char* OutputPathName) {
245    if(OutputPathName == NULL)
246        return true; /* no path name, just return */
247
248    setReflectJavaPathName(std::string(OutputPathName));
249    return true;
250}
251
252RSContext::~RSContext() {
253  /*    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
254    delete mRSExportFuncPragma;
255    delete mRSExportTypePragma;
256    delete mRSJavaPackageNamePragma;
257    delete mRSReflectLicensePragma;
258  */
259    delete mLicenseNote;
260    delete mTargetData;
261}
262
263}   /* namespace slang */
264