zonr | 6315f76 | 2010-10-05 15:35:14 +0800 | [diff] [blame] | 1 | #include "slang_rs_context.h" |
| 2 | |
| 3 | #include "llvm/LLVMContext.h" |
| 4 | #include "llvm/Target/TargetData.h" |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 5 | |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 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" |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 13 | |
zonr | 6315f76 | 2010-10-05 15:35:14 +0800 | [diff] [blame] | 14 | #include "slang.h" |
| 15 | #include "slang_rs_reflection.h" |
Zonr Chang | a41ce1d | 2010-10-06 02:23:12 +0800 | [diff] [blame^] | 16 | #include "slang_rs_exportable.h" |
zonr | 6315f76 | 2010-10-05 15:35:14 +0800 | [diff] [blame] | 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" |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 21 | |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 22 | using namespace slang; |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 23 | |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 24 | RSContext::RSContext(clang::Preprocessor *PP, |
| 25 | clang::ASTContext *Ctx, |
zonr | 6315f76 | 2010-10-05 15:35:14 +0800 | [diff] [blame] | 26 | const clang::TargetInfo *Target) |
| 27 | : mPP(PP), |
| 28 | mCtx(Ctx), |
| 29 | mTarget(Target), |
| 30 | mTargetData(NULL), |
| 31 | mLLVMContext(llvm::getGlobalContext()), |
| 32 | mExportAllNonStaticVars(false), |
| 33 | mExportAllNonStaticFuncs(false), |
| 34 | mLicenseNote(NULL) { |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 35 | // For #pragma rs export_var |
| 36 | PP->AddPragmaHandler( |
| 37 | "rs", RSPragmaHandler::CreatePragmaExportVarHandler(this)); |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 38 | |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 39 | // For #pragma rs export_var_all |
| 40 | PP->AddPragmaHandler( |
| 41 | "rs", RSPragmaHandler::CreatePragmaExportVarAllHandler(this)); |
Victor Hsieh | c6718b3 | 2010-06-23 09:29:44 +0800 | [diff] [blame] | 42 | |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 43 | // For #pragma rs export_func |
| 44 | PP->AddPragmaHandler( |
| 45 | "rs", RSPragmaHandler::CreatePragmaExportFuncHandler(this)); |
Victor Hsieh | c6718b3 | 2010-06-23 09:29:44 +0800 | [diff] [blame] | 46 | |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 47 | // For #pragma rs export_func_all |
| 48 | PP->AddPragmaHandler( |
| 49 | "rs", RSPragmaHandler::CreatePragmaExportFuncAllHandler(this)); |
Shih-wei Liao | 537446c | 2010-06-11 16:05:55 -0700 | [diff] [blame] | 50 | |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 51 | // For #pragma rs export_type |
| 52 | PP->AddPragmaHandler( |
| 53 | "rs", RSPragmaHandler::CreatePragmaExportTypeHandler(this)); |
Victor Hsieh | d8a0d18 | 2010-07-07 19:22:33 +0800 | [diff] [blame] | 54 | |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 55 | // For #pragma rs java_package_name |
| 56 | PP->AddPragmaHandler( |
| 57 | "rs", RSPragmaHandler::CreatePragmaJavaPackageNameHandler(this)); |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 58 | |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 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; |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 67 | } |
| 68 | |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 69 | bool RSContext::processExportVar(const clang::VarDecl *VD) { |
| 70 | assert(!VD->getName().empty() && "Variable name should not be empty"); |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 71 | |
zonr | 6315f76 | 2010-10-05 15:35:14 +0800 | [diff] [blame] | 72 | // TODO(zonr): some check on variable |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 73 | |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 74 | RSExportType *ET = RSExportType::CreateFromDecl(this, VD); |
| 75 | if (!ET) |
| 76 | return false; |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 77 | |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 78 | RSExportVar *EV = new RSExportVar(this, VD, ET); |
| 79 | if (EV == NULL) |
| 80 | return false; |
| 81 | else |
| 82 | mExportVars.push_back(EV); |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 83 | |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 84 | return true; |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 85 | } |
| 86 | |
zonr | 6315f76 | 2010-10-05 15:35:14 +0800 | [diff] [blame] | 87 | bool RSContext::processExportFunc(const clang::FunctionDecl *FD) { |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 88 | assert(!FD->getName().empty() && "Function name should not be empty"); |
Shih-wei Liao | 537446c | 2010-06-11 16:05:55 -0700 | [diff] [blame] | 89 | |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 90 | if (!FD->isThisDeclarationADefinition()) |
| 91 | return false; |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 92 | |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 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 | } |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 98 | |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 99 | RSExportFunc *EF = RSExportFunc::Create(this, FD); |
| 100 | if (EF == NULL) |
| 101 | return false; |
| 102 | else |
| 103 | mExportFuncs.push_back(EF); |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 104 | |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 105 | return true; |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 106 | } |
| 107 | |
| 108 | |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 109 | bool RSContext::processExportType(const llvm::StringRef &Name) { |
| 110 | clang::TranslationUnitDecl *TUDecl = mCtx->getTranslationUnitDecl(); |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 111 | |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 112 | assert(TUDecl != NULL && "Translation unit declaration (top-level " |
| 113 | "declaration) is null object"); |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 114 | |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 115 | const clang::IdentifierInfo *II = mPP->getIdentifierInfo(Name); |
| 116 | if (II == NULL) |
zonr | 6315f76 | 2010-10-05 15:35:14 +0800 | [diff] [blame] | 117 | // TODO(zonr): alert identifier @Name mark as an exportable type cannot be |
| 118 | // found |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 119 | return false; |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 120 | |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 121 | clang::DeclContext::lookup_const_result R = TUDecl->lookup(II); |
| 122 | RSExportType *ET = NULL; |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 123 | |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 124 | RSExportPointerType::IntegerType = mCtx->IntTy.getTypePtr(); |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 125 | |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 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; |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 131 | |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 132 | switch (ND->getKind()) { |
| 133 | case clang::Decl::Typedef: { |
| 134 | T = static_cast<const clang::TypedefDecl*>( |
| 135 | ND)->getCanonicalDecl()->getUnderlyingType().getTypePtr(); |
| 136 | break; |
| 137 | } |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 138 | case clang::Decl::Record: { |
| 139 | T = static_cast<const clang::RecordDecl*>(ND)->getTypeForDecl(); |
| 140 | break; |
| 141 | } |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 142 | default: { |
| 143 | // unsupported, skip |
| 144 | break; |
Shih-wei Liao | ac91815 | 2010-08-29 02:43:24 -0700 | [diff] [blame] | 145 | } |
| 146 | } |
Shih-wei Liao | 537446c | 2010-06-11 16:05:55 -0700 | [diff] [blame] | 147 | |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 148 | if (T != NULL) |
| 149 | ET = RSExportType::Create(this, T); |
| 150 | } |
| 151 | |
| 152 | RSExportPointerType::IntegerType = NULL; |
| 153 | |
| 154 | return (ET != NULL); |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 155 | } |
| 156 | |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 157 | void 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(...), " |
zonr | 6315f76 | 2010-10-05 15:35:14 +0800 | [diff] [blame] | 163 | "#pragma rs export_var_all, or #pragma rs " |
| 164 | "export_func_all\n"); |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 165 | } |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 166 | |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 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()); |
Ying Wang | 3f8b44d | 2010-09-04 01:17:01 -0700 | [diff] [blame] | 180 | } |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 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 | } |
Ying Wang | 3f8b44d | 2010-09-04 01:17:01 -0700 | [diff] [blame] | 201 | } |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 202 | } |
Ying Wang | 3f8b44d | 2010-09-04 01:17:01 -0700 | [diff] [blame] | 203 | |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 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()); |
Ying Wang | 3f8b44d | 2010-09-04 01:17:01 -0700 | [diff] [blame] | 212 | } |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 213 | } |
Shih-wei Liao | 537446c | 2010-06-11 16:05:55 -0700 | [diff] [blame] | 214 | |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 215 | return; |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 216 | } |
| 217 | |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 218 | bool 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); |
Shih-wei Liao | 6de8927 | 2010-07-15 15:26:20 -0700 | [diff] [blame] | 225 | |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 226 | if (mExportTypes.insert(NewItem)) { |
Shih-wei Liao | 6de8927 | 2010-07-15 15:26:20 -0700 | [diff] [blame] | 227 | return true; |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 228 | } else { |
| 229 | free(NewItem); |
| 230 | return false; |
| 231 | } |
| 232 | } |
| 233 | |
| 234 | bool RSContext::reflectToJava(const char *OutputPackageName, |
| 235 | const std::string &InputFileName, |
| 236 | const std::string &OutputBCFileName, |
| 237 | char realPackageName[], |
| 238 | int bSize) { |
| 239 | if (realPackageName != NULL) { |
| 240 | *realPackageName = 0; |
| 241 | } |
| 242 | |
| 243 | if (OutputPackageName == NULL) { |
| 244 | if (!mReflectJavaPackageName.empty()) { |
| 245 | OutputPackageName = mReflectJavaPackageName.c_str(); |
| 246 | } else { |
| 247 | // no package name, just return |
| 248 | return true; |
| 249 | } |
| 250 | } |
| 251 | |
| 252 | // Copy back the really applied package name |
| 253 | if (realPackageName != NULL) { |
| 254 | strncpy(realPackageName, OutputPackageName, bSize - 1); |
| 255 | } |
| 256 | |
| 257 | RSReflection *R = new RSReflection(this); |
| 258 | bool ret = R->reflect(OutputPackageName, InputFileName, OutputBCFileName); |
zonr | 6315f76 | 2010-10-05 15:35:14 +0800 | [diff] [blame] | 259 | if (!ret) |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 260 | fprintf(stderr, "RSContext::reflectToJava : failed to do reflection " |
| 261 | "(%s)\n", R->getLastError()); |
| 262 | delete R; |
| 263 | return ret; |
| 264 | } |
| 265 | |
| 266 | bool RSContext::reflectToJavaPath(const char *OutputPathName) { |
| 267 | if (OutputPathName == NULL) |
| 268 | // no path name, just return |
| 269 | return true; |
| 270 | |
| 271 | setReflectJavaPathName(std::string(OutputPathName)); |
| 272 | return true; |
Shih-wei Liao | 6de8927 | 2010-07-15 15:26:20 -0700 | [diff] [blame] | 273 | } |
| 274 | |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 275 | RSContext::~RSContext() { |
Shih-wei Liao | 9ef2f78 | 2010-10-01 12:31:37 -0700 | [diff] [blame] | 276 | delete mLicenseNote; |
| 277 | delete mTargetData; |
Zonr Chang | a41ce1d | 2010-10-06 02:23:12 +0800 | [diff] [blame^] | 278 | for (ExportableList::iterator I = mExportables.begin(), |
| 279 | E = mExportables.end(); |
| 280 | I != E; |
| 281 | I++) { |
| 282 | delete *I; |
| 283 | } |
Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 284 | } |