slang.cpp revision 807a0eaf3c19dc067becdca46a10e8c703d1e871
1#include "slang.hpp" 2#include "libslang.h" 3 4#include "llvm/ADT/Twine.h" /* for class llvm::Twine */ 5 6#include "llvm/Target/TargetSelect.h" /* for function LLVMInitialize[ARM|X86][TargetInfo|Target|AsmPrinter]() */ 7 8#include "llvm/Support/MemoryBuffer.h" /* for class llvm::MemoryBuffer */ 9#include "llvm/Support/ErrorHandling.h" /* for function llvm::install_fatal_error_handler() */ 10#include "llvm/Support/ManagedStatic.h" /* for class llvm::llvm_shutdown */ 11 12#include "clang/Basic/TargetInfo.h" /* for class clang::TargetInfo */ 13#include "clang/Basic/LangOptions.h" /* for class clang::LangOptions */ 14#include "clang/Basic/TargetOptions.h" /* for class clang::TargetOptions */ 15 16#include "clang/Frontend/FrontendDiagnostic.h" /* for clang::diag::* */ 17 18#include "clang/Sema/ParseAST.h" /* for function clang::ParseAST() */ 19 20#if defined(__arm__) 21# define DEFAULT_TARGET_TRIPLE_STRING "armv7-none-linux-gnueabi" 22#elif defined(__x86_64__) 23# define DEFAULT_TARGET_TRIPLE_STRING "x86_64-unknown-linux" 24#else 25# define DEFAULT_TARGET_TRIPLE_STRING "i686-unknown-linux" // let's use x86 as default target 26#endif 27 28namespace slang { 29 30bool Slang::GlobalInitialized = false; 31 32/* Language option (define the language feature for compiler such as C99) */ 33LangOptions Slang::LangOpts; 34 35/* Code generation option for the compiler */ 36CodeGenOptions Slang::CodeGenOpts; 37 38const std::string Slang::TargetDescription = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-n32"; 39 40/* The named of metadata node that pragma resides (should be synced with bcc.cpp) */ 41const llvm::Twine Slang::PragmaMetadataName = "#pragma"; 42 43void Slang::GlobalInitialization() { 44 if(!GlobalInitialized) { 45 /* We only support x86, x64 and ARM target */ 46 47 /* For ARM */ 48 LLVMInitializeARMTargetInfo(); 49 LLVMInitializeARMTarget(); 50 LLVMInitializeARMAsmPrinter(); 51 52 /* For x86 and x64 */ 53 LLVMInitializeX86TargetInfo(); 54 LLVMInitializeX86Target(); 55 LLVMInitializeX86AsmPrinter(); 56 57 /* Please refer to clang/include/clang/Basic/LangOptions.h for setting up the options */ 58 LangOpts.RTTI = 0; /* turn off the RTTI information support */ 59 LangOpts.NeXTRuntime = 0; /* turn off the NeXT runtime uses */ 60 LangOpts.Bool = 1; /* turn on 'bool', 'true', 'false' keywords. */ 61 62 CodeGenOpts.OptimizationLevel = 3; /* -O3 */ 63 64 GlobalInitialized = true; 65 } 66 67 return; 68} 69 70void Slang::LLVMErrorHandler(void *UserData, const std::string &Message) { 71 Diagnostic* Diags = static_cast<Diagnostic*>(UserData); 72 Diags->Report(clang::diag::err_fe_error_backend) << Message; 73 exit(1); 74} 75 76void Slang::createTarget(const char* Triple, const char* CPU, const char** Features) { 77 if(Triple != NULL) 78 mTargetOpts.Triple = Triple; 79 else 80 mTargetOpts.Triple = DEFAULT_TARGET_TRIPLE_STRING; 81 82 if(CPU != NULL) 83 mTargetOpts.CPU = CPU; 84 85 mTarget.reset(TargetInfo::CreateTargetInfo(*mDiagnostics, mTargetOpts)); 86 87 if(Features != NULL) 88 for(int i=0;Features[i]!=NULL;i++) 89 mTargetOpts.Features.push_back(Features[i]); 90 91 return; 92} 93 94Slang::Slang(const char* Triple, const char* CPU, const char** Features) : 95 mOutputType(SlangCompilerOutput_Default), 96 mAllowRSPrefix(false) 97{ 98 GlobalInitialization(); 99 100 createDiagnostic(); 101 llvm::install_fatal_error_handler(LLVMErrorHandler, mDiagnostics.get()); 102 103 createTarget(Triple, CPU, Features); 104 createFileManager(); 105 createSourceManager(); 106 107 return; 108} 109 110bool Slang::setInputSource(llvm::StringRef inputFile, const char* text, size_t textLength) { 111 mInputFileName = inputFile.str(); 112 113 /* Reset the ID tables if we are reusing the SourceManager */ 114 mSourceMgr->clearIDTables(); 115 116 /* Load the source */ 117 llvm::MemoryBuffer *SB = llvm::MemoryBuffer::getMemBuffer(text, text + textLength); 118 mSourceMgr->createMainFileIDForMemBuffer(SB); 119 120 if(mSourceMgr->getMainFileID().isInvalid()) { 121 mDiagnostics->Report(clang::diag::err_fe_error_reading) << inputFile; 122 return false; 123 } 124 125 return true; 126} 127 128bool Slang::setInputSource(llvm::StringRef inputFile) { 129 mInputFileName = inputFile.str(); 130 131 mSourceMgr->clearIDTables(); 132 133 const FileEntry* File = mFileMgr->getFile(inputFile); 134 if(File) 135 mSourceMgr->createMainFileID(File, SourceLocation()); 136 137 if(mSourceMgr->getMainFileID().isInvalid()) { 138 mDiagnostics->Report(clang::diag::err_fe_error_reading) << inputFile; 139 return false; 140 } 141 142 return true; 143} 144 145void Slang::setOutputType(SlangCompilerOutputTy outputType) { 146 mOutputType = outputType; 147 if( mOutputType != SlangCompilerOutput_Assembly && 148 mOutputType != SlangCompilerOutput_LL && 149 mOutputType != SlangCompilerOutput_Bitcode && 150 mOutputType != SlangCompilerOutput_Nothing && 151 mOutputType != SlangCompilerOutput_Obj) 152 mOutputType = SlangCompilerOutput_Default; 153 return; 154} 155 156static void _mkdir_given_a_file(const char *file) { 157 char buf[256]; 158 char *tmp, *p = NULL; 159 size_t len = strlen(file); 160 161 if (len + 1 <= sizeof(buf)) 162 tmp = buf; 163 else 164 tmp = new char [len + 1]; 165 166 strcpy(tmp, file); 167 168 if (tmp[len - 1] == '/') 169 tmp[len - 1] = 0; 170 171 for (p = tmp + 1; *p; p++) { 172 if (*p == '/') { 173 *p = 0; 174 mkdir(tmp, S_IRWXU); 175 *p = '/'; 176 } 177 } 178 179 if (tmp != buf) 180 delete[] tmp; 181} 182 183bool Slang::setOutput(const char* outputFile) { 184 std::string Error; 185 186 _mkdir_given_a_file(outputFile); 187 188 switch(mOutputType) { 189 case SlangCompilerOutput_Assembly: 190 case SlangCompilerOutput_LL: 191 mOS.reset( new llvm::raw_fd_ostream(outputFile, Error, 0) ); 192 break; 193 194 case SlangCompilerOutput_Nothing: 195 mOS.reset(); 196 break; 197 198 case SlangCompilerOutput_Obj: 199 case SlangCompilerOutput_Bitcode: 200 default: 201 mOS.reset( new llvm::raw_fd_ostream(outputFile, Error, llvm::raw_fd_ostream::F_Binary) ); 202 break; 203 } 204 205 if(!Error.empty()) { 206 mOS.reset(); 207 mDiagnostics->Report(clang::diag::err_fe_error_opening) << outputFile << Error; 208 return false; 209 } 210 211 mOutputFileName = outputFile; 212 213 return true; 214} 215 216int Slang::compile() { 217 if((mDiagnostics->getNumErrors() > 0) || (mOS.get() == NULL)) 218 return mDiagnostics->getNumErrors(); 219 220 /* Here is per-compilation needed initialization */ 221 createPreprocessor(); 222 createASTContext(); 223 createRSContext(); 224 //createBackend(); 225 createRSBackend(); 226 227 /* Inform the diagnostic client we are processing a source file */ 228 mDiagClient->BeginSourceFile(LangOpts, mPP.get()); 229 230 /* The core of the slang compiler */ 231 ParseAST(*mPP, mBackend.get(), *mASTContext); 232 233 /* The compilation ended, clear up */ 234 mBackend.reset(); 235 mASTContext.reset(); 236 mPP.reset(); 237 238 /* Inform the diagnostic client we are done with previous source file */ 239 mDiagClient->EndSourceFile(); 240 241 return mDiagnostics->getNumErrors(); 242} 243 244bool Slang::reflectToJava(const char* outputPackageName) { 245 if(mRSContext.get()) 246 return mRSContext->reflectToJava(outputPackageName, mInputFileName, mOutputFileName); 247 else 248 return false; 249} 250 251bool Slang::reflectToJavaPath(const char* outputPathName) { 252 if(mRSContext.get()) 253 return mRSContext->reflectToJavaPath(outputPathName); 254 else 255 return false; 256} 257 258void Slang::getPragmas(size_t* actualStringCount, size_t maxStringCount, char** strings) { 259 int stringCount = mPragmas.size() * 2; 260 261 if(actualStringCount) 262 *actualStringCount = stringCount; 263 if(stringCount > maxStringCount) 264 stringCount = maxStringCount; 265 if(strings) 266 for(PragmaList::const_iterator it = mPragmas.begin(); 267 stringCount > 0; 268 stringCount-=2, it++) 269 { 270 *strings++ = const_cast<char*>(it->first.c_str()); 271 *strings++ = const_cast<char*>(it->second.c_str()); 272 } 273 274 return; 275} 276 277Slang::~Slang() { 278 llvm::llvm_shutdown(); 279 return; 280} 281 282} /* namespace slang */ 283