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