slang_rs_context.cpp revision f83d3c396d5d7eacd97cf0a5d3b6a01d75535b67
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{
41    /* For #pragma rs export_var */
42    mRSExportVarPragma = RSPragmaHandler::CreatePragmaExportVarHandler(this);
43    if(mRSExportVarPragma != NULL)
44        PP->AddPragmaHandler("rs", mRSExportVarPragma);
45
46    /* For #pragma rs export_var_all */
47    mRSExportVarAllPragma = RSPragmaHandler::CreatePragmaExportVarAllHandler(this);
48    if(mRSExportVarAllPragma != NULL)
49        PP->AddPragmaHandler("rs", mRSExportVarAllPragma);
50
51    /* For #pragma rs export_func */
52    mRSExportFuncPragma = RSPragmaHandler::CreatePragmaExportFuncHandler(this);
53    if(mRSExportFuncPragma != NULL)
54        PP->AddPragmaHandler("rs", mRSExportFuncPragma);
55
56    /* For #pragma rs export_func_all */
57    mRSExportFuncAllPragma = RSPragmaHandler::CreatePragmaExportFuncAllHandler(this);
58    if(mRSExportFuncAllPragma != NULL)
59        PP->AddPragmaHandler("rs", mRSExportFuncAllPragma);
60
61    /* For #pragma rs export_type */
62    mRSExportTypePragma = RSPragmaHandler::CreatePragmaExportTypeHandler(this);
63    if(mRSExportTypePragma != NULL)
64        PP->AddPragmaHandler("rs", mRSExportTypePragma);
65
66    /* For #pragma rs java_package_name */
67    mRSJavaPackageNamePragma = RSPragmaHandler::CreatePragmaJavaPackageNameHandler(this);
68    if(mRSJavaPackageNamePragma != NULL)
69        PP->AddPragmaHandler("rs", mRSJavaPackageNamePragma);
70
71    /* For #pragma rs set_reflect_license */
72    mRSReflectLicensePragma = RSPragmaHandler::RSPragmaHandler::CreatePragmaReflectLicenseHandler(this);
73    if (mRSReflectLicensePragma != NULL)
74        PP->AddPragmaHandler("rs", mRSReflectLicensePragma);
75
76    /* Prepare target data */
77    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);
88    if(!ET)
89        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");
102
103    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
121bool RSContext::processExportType(const llvm::StringRef& Name) {
122    TranslationUnitDecl* TUDecl = mCtx->getTranslationUnitDecl();
123
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
135    RSExportPointerType::IntegerType = mCtx->IntTy.getTypePtr();
136
137    for(DeclContext::lookup_const_iterator I = R.first;
138        I != R.second;
139        I++)
140    {
141        NamedDecl* const ND = *I;
142        ASTLocation* LastLoc = new ASTLocation(ND);
143        ASTLocation AL = ResolveLocationInAST(*mCtx, ND->getLocStart(), LastLoc);
144
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
174void RSContext::processExport() {
175    /* Export variable */
176    TranslationUnitDecl* TUDecl = mCtx->getTranslationUnitDecl();
177    for(DeclContext::decl_iterator DI = TUDecl->decls_begin();
178        DI != TUDecl->decls_end();
179        DI++)
180    {
181        if (DI->getKind() == Decl::Var) {
182            VarDecl* VD = (VarDecl*) (*DI);
183            if (mExportAllNonStaticVars && VD->getLinkage() == ExternalLinkage) {
184                if (!processExportVar(VD)) {
185                    printf("RSContext::processExport : failed to export var '%s'\n", VD->getNameAsCString());
186                }
187            } else {
188                NeedExportVarSet::iterator EI = mNeedExportVars.find(VD->getName());
189                if(EI != mNeedExportVars.end() && processExportVar(VD))
190                    mNeedExportVars.erase(EI);
191            }
192        } else if (DI->getKind() == Decl::Function) {
193            FunctionDecl* FD = (FunctionDecl*) (*DI);
194            if (mExportAllNonStaticFuncs && FD->getLinkage() == ExternalLinkage) {
195                if (!processExportFunc(FD)) {
196                    printf("RSContext::processExport : failed to export func '%s'\n", FD->getNameAsCString());
197                }
198            } else {
199                NeedExportFuncSet::iterator EI = mNeedExportFuncs.find(FD->getName());
200                if(EI != mNeedExportFuncs.end() && processExportFunc(FD))
201                    mNeedExportFuncs.erase(EI);
202            }
203        }
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++)
210        if(!processExportType(EI->getKey()))
211            printf("RSContext::processExport : failed to export type '%s'\n", EI->getKey().str().c_str());
212
213
214    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
228bool 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
235    RSReflection* R = new RSReflection(this);
236    bool ret = R->reflect(OutputPackageName, InputFileName, OutputBCFileName);
237    if(!ret)
238        printf("RSContext::reflectToJava : failed to do reflection (%s)\n", R->getLastError());
239    delete R;
240    return ret;
241}
242
243bool 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
251RSContext::~RSContext() {
252  /*    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
253    delete mRSExportFuncPragma;
254    delete mRSExportTypePragma;
255    delete mRSJavaPackageNamePragma;
256    delete mRSReflectLicensePragma;
257  */
258    delete mLicenseNote;
259    delete mTargetData;
260}
261
262}   /* namespace slang */
263