slang_rs_context.cpp revision 537446c9542fdda458920876ed8a020a97ddf7a4
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/Index/Utils.h" /* for class clang::idx::ResolveLocationInAST() */ 12#include "clang/AST/DeclBase.h" /* for class clang::Decl and clang::DeclContext */ 13#include "clang/AST/ASTContext.h" /* for class clang::ASTContext */ 14#include "clang/Basic/TargetInfo.h" /* for class clang::TargetInfo */ 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, const TargetInfo* Target) : 25 mPP(PP), 26 mTarget(Target), 27 mTargetData(NULL), 28 mLLVMContext(llvm::getGlobalContext()), 29 mRSExportVarPragma(NULL), 30 mRSExportFuncPragma(NULL), 31 mRSExportTypePragma(NULL), 32 mRSJavaPackageNamePragma(NULL) 33{ 34 /* For #pragma rs export_var */ 35 mRSExportVarPragma = RSPragmaHandler::CreatePragmaExportVarHandler(this); 36 if(mRSExportVarPragma != NULL) 37 PP->AddPragmaHandler("rs", mRSExportVarPragma); 38 39 /* For #pragma rs export_func */ 40 mRSExportFuncPragma = RSPragmaHandler::CreatePragmaExportFuncHandler(this); 41 if(mRSExportFuncPragma != NULL) 42 PP->AddPragmaHandler("rs", mRSExportFuncPragma); 43 44 /* For #pragma rs export_type */ 45 mRSExportTypePragma = RSPragmaHandler::CreatePragmaExportTypeHandler(this); 46 if(mRSExportTypePragma != NULL) 47 PP->AddPragmaHandler("rs", mRSExportTypePragma); 48 49 /* For #pragma rs java_package_name */ 50 mRSJavaPackageNamePragma = RSPragmaHandler::CreatePragmaJavaPackageNameHandler(this); 51 if(mRSJavaPackageNamePragma != NULL) 52 PP->AddPragmaHandler("rs", mRSJavaPackageNamePragma); 53 54 mTargetData = new llvm::TargetData(Slang::TargetDescription); 55 56 return; 57} 58 59bool RSContext::processExportVar(const VarDecl* VD) { 60 assert(!VD->getName().empty() && "Variable name should not be empty"); 61 62 /* TODO: some check on variable */ 63 64 RSExportType* ET = RSExportType::CreateFromDecl(this, VD); 65 if(!ET) 66 return false; 67 68 RSExportVar* EV = new RSExportVar(this, VD, ET); 69 if(EV == NULL) 70 return false; 71 else 72 mExportVars.push_back(EV); 73 74 return true; 75} 76 77bool RSContext::processExportFunc(const FunctionDecl* FD) { 78 assert(!FD->getName().empty() && "Function name should not be empty"); 79 80 if(!FD->isThisDeclarationADefinition()) 81 return false; 82 83 if(FD->getStorageClass() != FunctionDecl::None) { 84 printf("RSContext::processExportFunc : cannot export extern or static function '%s'\n", FD->getName().str().c_str()); 85 return false; 86 } 87 88 RSExportFunc* EF = RSExportFunc::Create(this, FD); 89 if(EF == NULL) 90 return false; 91 else 92 mExportFuncs.push_back(EF); 93 94 return true; 95} 96 97 98bool RSContext::processExportType(ASTContext& Ctx, const llvm::StringRef& Name) { 99 TranslationUnitDecl* TUDecl = Ctx.getTranslationUnitDecl(); 100 101 assert(TUDecl != NULL && "Translation unit declaration (top-level declaration) is null object"); 102 103 const IdentifierInfo* II = mPP->getIdentifierInfo(Name); 104 if(II == NULL) 105 /* TODO: error: identifier @Name mark as an exportable type cannot be found */ 106 return false; 107 108 DeclContext::lookup_const_result R = TUDecl->lookup(II); 109 bool Done = false; 110 RSExportType* ET = NULL; 111 112 RSExportPointerType::IntegerType = Ctx.IntTy.getTypePtr(); 113 114 for(DeclContext::lookup_const_iterator I = R.first; 115 I != R.second; 116 I++) 117 { 118 NamedDecl* const ND = *I; 119 ASTLocation* LastLoc = new ASTLocation(ND); 120 ASTLocation AL = ResolveLocationInAST(Ctx, ND->getLocStart(), LastLoc); 121 122 delete LastLoc; 123 if(AL.isDecl()) { 124 Decl* D = AL.dyn_AsDecl(); 125 const Type* T = NULL; 126 127 switch(D->getKind()) { 128 case Decl::Typedef: 129 T = static_cast<const TypedefDecl*>(D)->getCanonicalDecl()->getUnderlyingType().getTypePtr(); 130 break; 131 132 case Decl::Record: 133 T = static_cast<const RecordDecl*>(D)->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 146 RSExportPointerType::IntegerType = NULL; 147 148 return (ET != NULL); 149} 150 151void RSContext::processExport(ASTContext& Ctx) { 152 /* Export variable */ 153 TranslationUnitDecl* TUDecl = Ctx.getTranslationUnitDecl(); 154 for(DeclContext::decl_iterator DI = TUDecl->decls_begin(); 155 DI != TUDecl->decls_end(); 156 DI++) 157 { 158 if(DI->getKind() == Decl::Var) { 159 VarDecl* VD = (VarDecl*) (*DI); 160 NeedExportVarSet::iterator EI = mNeedExportVars.find(VD->getName()); 161 if(EI != mNeedExportVars.end() && processExportVar(VD)) 162 mNeedExportVars.erase(EI); 163 } else if(DI->getKind() == Decl::Function) { 164 FunctionDecl* FD = (FunctionDecl*) (*DI); 165 NeedExportFuncSet::iterator EI = mNeedExportFuncs.find(FD->getName()); 166 if(EI != mNeedExportFuncs.end() && processExportFunc(FD)) 167 mNeedExportFuncs.erase(EI); 168 } 169 } 170 171 /* Finally, export type forcely set to be exported by user */ 172 for(NeedExportTypeSet::const_iterator EI = mNeedExportTypes.begin(); 173 EI != mNeedExportTypes.end(); 174 EI++) 175 if(!processExportType(Ctx, EI->getKey())) 176 printf("RSContext::processExport : failed to export type '%s'\n", EI->getKey().str().c_str()); 177 178 179 return; 180} 181 182bool RSContext::insertExportType(const llvm::StringRef& TypeName, RSExportType* ET) { 183 ExportTypeMap::value_type* NewItem = ExportTypeMap::value_type::Create(TypeName.begin(), TypeName.end(), mExportTypes.getAllocator(), ET); 184 185 if(mExportTypes.insert(NewItem)) { 186 return true; 187 } else { 188 delete NewItem; 189 return false; 190 } 191} 192 193bool RSContext::reflectToJava(const char* OutputPackageName, const std::string& InputFileName, const std::string& OutputBCFileName) { 194 if(OutputPackageName == NULL) 195 if(!mReflectJavaPackageName.empty()) 196 OutputPackageName = mReflectJavaPackageName.c_str(); 197 else 198 return true; /* no package name, just return */ 199 200 RSReflection* R = new RSReflection(this); 201 bool ret = R->reflect(OutputPackageName, InputFileName, OutputBCFileName); 202 if(!ret) 203 printf("RSContext::reflectToJava : failed to do reflection (%s)\n", R->getLastError()); 204 delete R; 205 return ret; 206} 207 208RSContext::~RSContext() { 209 delete mRSExportVarPragma; 210 delete mRSExportFuncPragma; 211 delete mRSExportTypePragma; 212 delete mRSJavaPackageNamePragma; 213 214 delete mTargetData; 215} 216 217} /* namespace slang */ 218