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