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