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