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