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