blob: 77e84672b07417877119ff6fc1b776a8160ff30e [file] [log] [blame]
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001#include "slang.hpp"
2#include "libslang.h"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07003#include "slang_rs_export_func.hpp"
Shih-wei Liao462aefd2010-06-04 15:32:04 -07004
Shih-wei Liao462aefd2010-06-04 15:32:04 -07005#include "llvm/Target/TargetSelect.h" /* for function LLVMInitialize[ARM|X86][TargetInfo|Target|AsmPrinter]() */
6
7#include "llvm/Support/MemoryBuffer.h" /* for class llvm::MemoryBuffer */
8#include "llvm/Support/ErrorHandling.h" /* for function llvm::install_fatal_error_handler() */
9#include "llvm/Support/ManagedStatic.h" /* for class llvm::llvm_shutdown */
10
11#include "clang/Basic/TargetInfo.h" /* for class clang::TargetInfo */
12#include "clang/Basic/LangOptions.h" /* for class clang::LangOptions */
13#include "clang/Basic/TargetOptions.h" /* for class clang::TargetOptions */
14
15#include "clang/Frontend/FrontendDiagnostic.h" /* for clang::diag::* */
16
Shih-wei Liaof52a6202010-09-10 17:40:53 -070017#include "clang/Parse/ParseAST.h" /* for function clang::ParseAST() */
Shih-wei Liao462aefd2010-06-04 15:32:04 -070018
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070019#include <stdlib.h>
20
21using namespace slang;
22
Shih-wei Liao462aefd2010-06-04 15:32:04 -070023#if defined(__arm__)
24# define DEFAULT_TARGET_TRIPLE_STRING "armv7-none-linux-gnueabi"
25#elif defined(__x86_64__)
26# define DEFAULT_TARGET_TRIPLE_STRING "x86_64-unknown-linux"
27#else
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070028// let's use x86 as default target
29# define DEFAULT_TARGET_TRIPLE_STRING "i686-unknown-linux"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070030#endif
31
Shih-wei Liao462aefd2010-06-04 15:32:04 -070032bool Slang::GlobalInitialized = false;
33
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070034// Language option (define the language feature for compiler such as C99)
35clang::LangOptions Slang::LangOpts;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070036
37/* Code generation option for the compiler */
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070038clang::CodeGenOptions Slang::CodeGenOpts;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070039
40const 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";
41
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070042// The named of metadata node that pragma resides (should be synced with
43// bcc.cpp)
Shih-wei Liaof52a6202010-09-10 17:40:53 -070044const llvm::StringRef Slang::PragmaMetadataName = "#pragma";
Shih-wei Liao462aefd2010-06-04 15:32:04 -070045
46void Slang::GlobalInitialization() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070047 if (!GlobalInitialized) {
48 // We only support x86, x64 and ARM target
Shih-wei Liao462aefd2010-06-04 15:32:04 -070049
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070050 // For ARM
51 LLVMInitializeARMTargetInfo();
52 LLVMInitializeARMTarget();
53 LLVMInitializeARMAsmPrinter();
Shih-wei Liao462aefd2010-06-04 15:32:04 -070054
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070055 // For x86 and x64
56 LLVMInitializeX86TargetInfo();
57 LLVMInitializeX86Target();
58 LLVMInitializeX86AsmPrinter();
Shih-wei Liao462aefd2010-06-04 15:32:04 -070059
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070060 // Please refer to clang/include/clang/Basic/LangOptions.h to set up
61 // the options.
62 LangOpts.RTTI = 0; // Turn off the RTTI information support
63 LangOpts.NeXTRuntime = 0; // Turn off the NeXT runtime uses
64 LangOpts.Bool = 1; // Turn on 'bool', 'true', 'false' keywords
Shih-wei Liao462aefd2010-06-04 15:32:04 -070065
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070066 CodeGenOpts.OptimizationLevel = 3; /* -O3 */
Shih-wei Liao462aefd2010-06-04 15:32:04 -070067
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070068 GlobalInitialized = true;
69 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -070070
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070071 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070072}
73
74void Slang::LLVMErrorHandler(void *UserData, const std::string &Message) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070075 clang::Diagnostic* Diags = static_cast<clang::Diagnostic*>(UserData);
76 Diags->Report(clang::diag::err_fe_error_backend) << Message;
77 exit(1);
Shih-wei Liao462aefd2010-06-04 15:32:04 -070078}
79
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070080void Slang::createTarget(const char* Triple, const char* CPU,
81 const char** Features) {
82 if (Triple != NULL)
83 mTargetOpts.Triple = Triple;
84 else
85 mTargetOpts.Triple = DEFAULT_TARGET_TRIPLE_STRING;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070086
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070087 if (CPU != NULL)
88 mTargetOpts.CPU = CPU;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070089
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070090 mTarget.reset(clang::TargetInfo::CreateTargetInfo(*mDiagnostics,
91 mTargetOpts));
Shih-wei Liao462aefd2010-06-04 15:32:04 -070092
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070093 if (Features != NULL)
94 for (int i = 0; Features[i]!=NULL; i++)
95 mTargetOpts.Features.push_back(Features[i]);
Shih-wei Liao462aefd2010-06-04 15:32:04 -070096
97 return;
98}
99
Shih-wei Liao68e8e9f2010-07-18 18:46:49 -0700100void Slang::createPreprocessor() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700101 // Default only search header file in current dir
102 clang::HeaderSearch *HS = new clang::HeaderSearch(*mFileMgr);
Shih-wei Liao68e8e9f2010-07-18 18:46:49 -0700103
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700104 mPP.reset(new clang::Preprocessor(*mDiagnostics,
105 LangOpts,
106 *mTarget,
107 *mSourceMgr,
108 *HS,
109 NULL,
110 /* OwnsHeaderSearch */true));
111 // Initialize the prepocessor
Shih-wei Liao68e8e9f2010-07-18 18:46:49 -0700112 mPragmas.clear();
Shih-wei Liaof52a6202010-09-10 17:40:53 -0700113 mPP->AddPragmaHandler(new PragmaRecorder(mPragmas));
Shih-wei Liao68e8e9f2010-07-18 18:46:49 -0700114
Shih-wei Liao60de5bd2010-07-21 12:43:30 -0700115 std::string inclFiles("#include \"rs_types.rsh\"");
116 mPP->setPredefines(inclFiles + "\n" + "#include \"rs_math.rsh\"" + "\n");
117
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700118 std::vector<clang::DirectoryLookup> SearchList;
119 for (unsigned i = 0; i < mIncludePaths.size(); ++i) {
120 if (const clang::DirectoryEntry *DE =
121 mFileMgr->getDirectory(mIncludePaths[i])) {
122 SearchList.push_back(clang::DirectoryLookup(DE,
123 clang::SrcMgr::C_System,
124 false,
125 false));
126 }
Shih-wei Liao90898282010-07-19 18:38:57 -0700127 }
128
129 HS->SetSearchPaths(SearchList, 1, false);
130
Shih-wei Liao68e8e9f2010-07-18 18:46:49 -0700131 return;
132}
133
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700134Slang::Slang(const char *Triple, const char *CPU, const char **Features) :
Kirk Stewart1fd85792010-07-07 09:51:23 -0700135 mOutputType(SlangCompilerOutput_Default),
136 mAllowRSPrefix(false)
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700137{
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700138 GlobalInitialization();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700139
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700140 createDiagnostic();
141 llvm::install_fatal_error_handler(LLVMErrorHandler, mDiagnostics.get());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700142
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700143 createTarget(Triple, CPU, Features);
144 createFileManager();
145 createSourceManager();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700146
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700147 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700148}
149
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700150bool Slang::setInputSource(llvm::StringRef inputFile, const char *text, size_t textLength) {
151 mInputFileName = inputFile.str();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700152
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700153 // Reset the ID tables if we are reusing the SourceManager
154 mSourceMgr->clearIDTables();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700155
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700156 // Load the source
157 llvm::MemoryBuffer *SB = llvm::MemoryBuffer::getMemBuffer(text, text + textLength);
158 mSourceMgr->createMainFileIDForMemBuffer(SB);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700159
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700160 if (mSourceMgr->getMainFileID().isInvalid()) {
161 mDiagnostics->Report(clang::diag::err_fe_error_reading) << inputFile;
162 return false;
163 }
164 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700165}
166
167bool Slang::setInputSource(llvm::StringRef inputFile) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700168 mInputFileName = inputFile.str();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700169
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700170 mSourceMgr->clearIDTables();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700171
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700172 const clang::FileEntry *File = mFileMgr->getFile(inputFile);
173 if (File)
174 mSourceMgr->createMainFileID(File);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700175
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700176 if (mSourceMgr->getMainFileID().isInvalid()) {
177 mDiagnostics->Report(clang::diag::err_fe_error_reading) << inputFile;
178 return false;
179 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700180
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700181 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700182}
183
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700184void Slang::addIncludePath(const char *path) {
185 mIncludePaths.push_back(path);
Ying Wange2e522f2010-09-01 13:24:01 -0700186}
187
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700188void Slang::setOutputType(SlangCompilerOutputTy outputType) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700189 mOutputType = outputType;
190 if ( mOutputType != SlangCompilerOutput_Assembly &&
191 mOutputType != SlangCompilerOutput_LL &&
192 mOutputType != SlangCompilerOutput_Bitcode &&
193 mOutputType != SlangCompilerOutput_Nothing &&
194 mOutputType != SlangCompilerOutput_Obj)
195 mOutputType = SlangCompilerOutput_Default;
196 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700197}
198
Shih-wei Liaob55d7ef2010-07-16 00:19:38 -0700199static void _mkdir_given_a_file(const char *file) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700200 char buf[256];
201 char *tmp, *p = NULL;
202 size_t len = strlen(file);
Shih-wei Liaob55d7ef2010-07-16 00:19:38 -0700203
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700204 if (len + 1 <= sizeof(buf))
205 tmp = buf;
206 else
207 tmp = new char [len + 1];
Che-Liang Chiou807a0ea2010-07-16 17:53:52 -0700208
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700209 strcpy(tmp, file);
Shih-wei Liaob55d7ef2010-07-16 00:19:38 -0700210
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700211 if (tmp[len - 1] == '/')
212 tmp[len - 1] = 0;
Shih-wei Liaob55d7ef2010-07-16 00:19:38 -0700213
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700214 for (p = tmp + 1; *p; p++) {
215 if (*p == '/') {
216 *p = 0;
217 mkdir(tmp, S_IRWXU);
218 *p = '/';
Shih-wei Liaob55d7ef2010-07-16 00:19:38 -0700219 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700220 }
Che-Liang Chiou807a0ea2010-07-16 17:53:52 -0700221
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700222 if (tmp != buf)
223 delete[] tmp;
Shih-wei Liaob55d7ef2010-07-16 00:19:38 -0700224}
225
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700226bool Slang::setOutput(const char *outputFile) {
227 std::string Error;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700228
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700229 _mkdir_given_a_file(outputFile);
Shih-wei Liaob55d7ef2010-07-16 00:19:38 -0700230
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700231 switch (mOutputType) {
232 case SlangCompilerOutput_Assembly:
233 case SlangCompilerOutput_LL: {
234 mOS.reset( new llvm::raw_fd_ostream(outputFile, Error, 0) );
235 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700236 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700237 case SlangCompilerOutput_Nothing: {
238 mOS.reset();
239 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700240 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700241 case SlangCompilerOutput_Obj:
242 case SlangCompilerOutput_Bitcode:
243 default: {
244 mOS.reset(new llvm::raw_fd_ostream(outputFile,
245 Error,
246 llvm::raw_fd_ostream::F_Binary));
247 break;
248 }
249 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700250
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700251 if (!Error.empty()) {
252 mOS.reset();
253 mDiagnostics->Report(clang::diag::err_fe_error_opening) << outputFile
254 << Error;
255 return false;
256 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700257
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700258 mOutputFileName = outputFile;
259
260 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700261}
262
263int Slang::compile() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700264 if ((mDiagnostics->getNumErrors() > 0) || (mOS.get() == NULL))
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700265 return mDiagnostics->getNumErrors();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700266
267 // Here is per-compilation needed initialization
268 createPreprocessor();
269 createASTContext();
270 createRSContext();
271 //createBackend();
272 createRSBackend();
273
274 // Inform the diagnostic client we are processing a source file
275 mDiagClient->BeginSourceFile(LangOpts, mPP.get());
276
277 // The core of the slang compiler
278 ParseAST(*mPP, mBackend.get(), *mASTContext);
279
280 // The compilation ended, clear up
281 mBackend.reset();
282 // Can't reset yet because the reflection later on still needs mRSContext
283 //mRSContext.reset();
284 mASTContext.reset();
285 mPP.reset();
286
287 // Inform the diagnostic client we are done with previous source file
288 mDiagClient->EndSourceFile();
289
290 return mDiagnostics->getNumErrors();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700291}
292
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700293bool Slang::reflectToJava(const char *outputPackageName,
294 char *realPackageName,
295 int bSize) {
296 if (mRSContext.get())
297 return mRSContext->reflectToJava(outputPackageName,
298 mInputFileName,
299 mOutputFileName,
300 realPackageName,
301 bSize);
302 else
303 return false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700304}
305
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700306bool Slang::reflectToJavaPath(const char *outputPathName) {
307 if (mRSContext.get())
308 return mRSContext->reflectToJavaPath(outputPathName);
309 else
310 return false;
Shih-wei Liao6de89272010-07-15 15:26:20 -0700311}
312
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700313void Slang::getPragmas(size_t *actualStringCount,
314 size_t maxStringCount,
315 char **strings) {
316 unsigned stringCount = mPragmas.size() * 2;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700317
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700318 if (actualStringCount)
319 *actualStringCount = stringCount;
320 if (stringCount > maxStringCount)
321 stringCount = maxStringCount;
322 if (strings)
323 for (PragmaList::const_iterator it = mPragmas.begin();
324 stringCount > 0;
325 stringCount -= 2, it++) {
326 *strings++ = const_cast<char*>(it->first.c_str());
327 *strings++ = const_cast<char*>(it->second.c_str());
328 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700329
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700330 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700331}
332
Shih-wei Liao4c9f7422010-08-05 04:30:02 -0700333typedef std::list<RSExportFunc*> ExportFuncList;
334
335const char* Slang::exportFuncs() {
336 std::string fNames;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700337 for (RSContext::const_export_func_iterator I=mRSContext->export_funcs_begin();
Shih-wei Liao4c9f7422010-08-05 04:30:02 -0700338 I != mRSContext->export_funcs_end();
339 ++I) {
340 RSExportFunc* func = *I;
341 fNames.push_back(',');
342 fNames.append(func->getName());
343 }
344 return fNames.c_str();
345}
346
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700347Slang::~Slang() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700348 llvm::llvm_shutdown();
349 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700350}