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