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