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