blob: 8127e5e5563cede13db73f87a60c10948125c4bf [file] [log] [blame]
Zonr Changc383a502010-10-12 01:52:08 +08001/*
2 * Copyright 2010, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
zonr6315f762010-10-05 15:35:14 +080017#include "slang.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070018
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070019#include <stdlib.h>
20
Stephen Hinese639eb52010-11-08 19:27:20 -080021#include <string>
22#include <vector>
23
24#include "clang/AST/ASTConsumer.h"
25#include "clang/AST/ASTContext.h"
26
27#include "clang/Basic/FileManager.h"
28#include "clang/Basic/LangOptions.h"
29#include "clang/Basic/SourceManager.h"
30#include "clang/Basic/TargetInfo.h"
31#include "clang/Basic/TargetOptions.h"
32
33#include "clang/Frontend/CodeGenOptions.h"
34#include "clang/Frontend/DiagnosticOptions.h"
35#include "clang/Frontend/DependencyOutputOptions.h"
36#include "clang/Frontend/FrontendDiagnostic.h"
37#include "clang/Frontend/TextDiagnosticPrinter.h"
38#include "clang/Frontend/Utils.h"
39
40#include "clang/Lex/Preprocessor.h"
41#include "clang/Lex/HeaderSearch.h"
42
43#include "clang/Parse/ParseAST.h"
44
45#include "llvm/Bitcode/ReaderWriter.h"
46
47// More force linking
48#include "llvm/Linker.h"
49
Zonr Chang08df36e2010-10-07 18:50:42 +080050// Force linking all passes/vmcore stuffs to libslang.so
51#include "llvm/LinkAllPasses.h"
52#include "llvm/LinkAllVMCore.h"
53
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080054#include "llvm/Support/raw_ostream.h"
zonr6315f762010-10-05 15:35:14 +080055#include "llvm/Support/MemoryBuffer.h"
56#include "llvm/Support/ErrorHandling.h"
57#include "llvm/Support/ManagedStatic.h"
58
Stephen Hinese639eb52010-11-08 19:27:20 -080059#include "llvm/System/Path.h"
zonr6315f762010-10-05 15:35:14 +080060
Stephen Hinese639eb52010-11-08 19:27:20 -080061#include "llvm/Target/TargetSelect.h"
Stephen Hinescc0efad2010-10-04 16:13:02 -070062
Stephen Hines6e6578a2011-02-07 18:05:48 -080063#include "slang_assert.h"
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080064#include "slang_backend.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080065#include "slang_utils.h"
Shih-wei Liaob81c6a42010-10-10 14:15:00 -070066
Zonr Chang08df36e2010-10-07 18:50:42 +080067namespace {
Zonr Chang08df36e2010-10-07 18:50:42 +080068
Stephen Hinese639eb52010-11-08 19:27:20 -080069struct ForceSlangLinking {
70 ForceSlangLinking() {
71 // We must reference the functions in such a way that compilers will not
72 // delete it all as dead code, even with whole program optimization,
73 // yet is effectively a NO-OP. As the compiler isn't smart enough
74 // to know that getenv() never returns -1, this will do the job.
75 if (std::getenv("bar") != reinterpret_cast<char*>(-1))
76 return;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -070077
Stephen Hinese639eb52010-11-08 19:27:20 -080078 // llvm-rs-link needs following functions existing in libslang.
79 llvm::ParseBitcodeFile(NULL, llvm::getGlobalContext(), NULL);
80 llvm::Linker::LinkModules(NULL, NULL, NULL);
Zonr Chang08df36e2010-10-07 18:50:42 +080081
Stephen Hinese639eb52010-11-08 19:27:20 -080082 // llvm-rs-cc need this.
83 new clang::TextDiagnosticPrinter(llvm::errs(),
84 clang::DiagnosticOptions());
85 }
86} ForceSlangLinking;
87
88} // namespace
89
90namespace slang {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070091
Shih-wei Liao462aefd2010-06-04 15:32:04 -070092#if defined(__arm__)
93# define DEFAULT_TARGET_TRIPLE_STRING "armv7-none-linux-gnueabi"
94#elif defined(__x86_64__)
95# define DEFAULT_TARGET_TRIPLE_STRING "x86_64-unknown-linux"
96#else
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070097// let's use x86 as default target
98# define DEFAULT_TARGET_TRIPLE_STRING "i686-unknown-linux"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070099#endif
100
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700101bool Slang::GlobalInitialized = false;
102
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700103// Language option (define the language feature for compiler such as C99)
104clang::LangOptions Slang::LangOpts;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700105
zonr6315f762010-10-05 15:35:14 +0800106// Code generation option for the compiler
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700107clang::CodeGenOptions Slang::CodeGenOpts;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700108
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700109// The named of metadata node that pragma resides (should be synced with
110// bcc.cpp)
Shih-wei Liaof52a6202010-09-10 17:40:53 -0700111const llvm::StringRef Slang::PragmaMetadataName = "#pragma";
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700112
Zonr Change8c263a2010-10-12 00:35:29 +0800113static inline llvm::tool_output_file *OpenOutputFile(const char *OutputFile,
114 unsigned Flags,
115 std::string* Error,
116 clang::Diagnostic* Diag) {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800117 slangAssert((OutputFile != NULL) && (Error != NULL) && (Diag != NULL) &&
118 "Invalid parameter!");
Zonr Change8c263a2010-10-12 00:35:29 +0800119
120 llvm::sys::Path OutputFilePath(OutputFile);
121
122 if (SlangUtils::CreateDirectoryWithParents(OutputFilePath.getDirname(),
123 Error)) {
124 llvm::tool_output_file *F =
125 new llvm::tool_output_file(OutputFile, *Error, Flags);
126 if (F != NULL)
127 return F;
128 }
129
130 // Report error here.
131 Diag->Report(clang::diag::err_fe_error_opening) << OutputFile << *Error;
132
133 return NULL;
134}
135
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700136void Slang::GlobalInitialization() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700137 if (!GlobalInitialized) {
138 // We only support x86, x64 and ARM target
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700139
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700140 // For ARM
141 LLVMInitializeARMTargetInfo();
142 LLVMInitializeARMTarget();
143 LLVMInitializeARMAsmPrinter();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700144
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700145 // For x86 and x64
146 LLVMInitializeX86TargetInfo();
147 LLVMInitializeX86Target();
148 LLVMInitializeX86AsmPrinter();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700149
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800150 // Please refer to include/clang/Basic/LangOptions.h to setup
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700151 // the options.
152 LangOpts.RTTI = 0; // Turn off the RTTI information support
153 LangOpts.NeXTRuntime = 0; // Turn off the NeXT runtime uses
Shih-wei Liao245eba12011-01-19 02:14:07 -0800154 LangOpts.C99 = 1;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700155
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700156 CodeGenOpts.OptimizationLevel = 3; /* -O3 */
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700157
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700158 GlobalInitialized = true;
159 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700160
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700161 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700162}
163
164void Slang::LLVMErrorHandler(void *UserData, const std::string &Message) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700165 clang::Diagnostic* Diags = static_cast<clang::Diagnostic*>(UserData);
166 Diags->Report(clang::diag::err_fe_error_backend) << Message;
167 exit(1);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700168}
169
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800170void Slang::createDiagnostic() {
171 mDiagnostics =
172 llvm::IntrusiveRefCntPtr<clang::Diagnostic>(new clang::Diagnostic());
173 mDiagClient = new DiagnosticBuffer();
174 // This takes the ownership of mDiagClient.
175 mDiagnostics->setClient(mDiagClient);
Zonr Chang641558f2010-10-12 21:07:06 +0800176 initDiagnostic();
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800177 return;
178}
179
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700180void Slang::createTarget(const std::string &Triple, const std::string &CPU,
181 const std::vector<std::string> &Features) {
182 if (!Triple.empty())
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700183 mTargetOpts.Triple = Triple;
184 else
185 mTargetOpts.Triple = DEFAULT_TARGET_TRIPLE_STRING;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700186
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700187 if (!CPU.empty())
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700188 mTargetOpts.CPU = CPU;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700189
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700190 if (!Features.empty())
191 mTargetOpts.Features = Features;
192
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700193 mTarget.reset(clang::TargetInfo::CreateTargetInfo(*mDiagnostics,
194 mTargetOpts));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700195
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700196 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700197}
198
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800199void Slang::createFileManager() {
200 mFileMgr.reset(new clang::FileManager());
201}
202
203void Slang::createSourceManager() {
204 mSourceMgr.reset(new clang::SourceManager(*mDiagnostics));
205 return;
206}
207
Shih-wei Liao68e8e9f2010-07-18 18:46:49 -0700208void Slang::createPreprocessor() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700209 // Default only search header file in current dir
210 clang::HeaderSearch *HS = new clang::HeaderSearch(*mFileMgr);
Shih-wei Liao68e8e9f2010-07-18 18:46:49 -0700211
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700212 mPP.reset(new clang::Preprocessor(*mDiagnostics,
213 LangOpts,
214 *mTarget,
215 *mSourceMgr,
216 *HS,
217 NULL,
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800218 /* OwnsHeaderSearch = */true));
Stephen Hines3fd0a942011-01-18 12:27:39 -0800219 // Initialize the preprocessor
Shih-wei Liao68e8e9f2010-07-18 18:46:49 -0700220 mPragmas.clear();
Stephen Hines3fd0a942011-01-18 12:27:39 -0800221 mPP->AddPragmaHandler(new PragmaRecorder(&mPragmas));
Shih-wei Liao68e8e9f2010-07-18 18:46:49 -0700222
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700223 std::vector<clang::DirectoryLookup> SearchList;
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800224 for (unsigned i = 0, e = mIncludePaths.size(); i != e; i++) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700225 if (const clang::DirectoryEntry *DE =
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800226 mFileMgr->getDirectory(mIncludePaths[i])) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700227 SearchList.push_back(clang::DirectoryLookup(DE,
228 clang::SrcMgr::C_System,
229 false,
230 false));
231 }
Shih-wei Liao90898282010-07-19 18:38:57 -0700232 }
233
234 HS->SetSearchPaths(SearchList, 1, false);
235
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800236 initPreprocessor();
Shih-wei Liao68e8e9f2010-07-18 18:46:49 -0700237 return;
238}
239
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800240void Slang::createASTContext() {
241 mASTContext.reset(new clang::ASTContext(LangOpts,
242 *mSourceMgr,
243 *mTarget,
244 mPP->getIdentifierTable(),
245 mPP->getSelectorTable(),
246 mPP->getBuiltinInfo(),
247 /* size_reserve = */0));
248 initASTContext();
249 return;
250}
251
252clang::ASTConsumer
253*Slang::createBackend(const clang::CodeGenOptions& CodeGenOpts,
254 llvm::raw_ostream *OS,
255 OutputType OT) {
Stephen Hinese639eb52010-11-08 19:27:20 -0800256 return new Backend(mDiagnostics.getPtr(),
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800257 CodeGenOpts,
258 mTargetOpts,
Stephen Hines3fd0a942011-01-18 12:27:39 -0800259 &mPragmas,
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800260 OS,
261 OT);
262}
263
Zonr Chang641558f2010-10-12 21:07:06 +0800264Slang::Slang() : mInitialized(false), mDiagClient(NULL), mOT(OT_Default) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700265 GlobalInitialization();
Zonr Chang641558f2010-10-12 21:07:06 +0800266 return;
267}
268
269void Slang::init(const std::string &Triple, const std::string &CPU,
270 const std::vector<std::string> &Features) {
271 if (mInitialized)
272 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700273
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700274 createDiagnostic();
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800275 llvm::install_fatal_error_handler(LLVMErrorHandler, mDiagnostics.getPtr());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700276
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700277 createTarget(Triple, CPU, Features);
278 createFileManager();
279 createSourceManager();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700280
Zonr Chang641558f2010-10-12 21:07:06 +0800281 mInitialized = true;
282
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700283 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700284}
285
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800286bool Slang::setInputSource(llvm::StringRef InputFile,
287 const char *Text,
288 size_t TextLength) {
289 mInputFileName = InputFile.str();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700290
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700291 // Reset the ID tables if we are reusing the SourceManager
292 mSourceMgr->clearIDTables();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700293
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700294 // Load the source
zonr6315f762010-10-05 15:35:14 +0800295 llvm::MemoryBuffer *SB =
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800296 llvm::MemoryBuffer::getMemBuffer(Text, Text + TextLength);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700297 mSourceMgr->createMainFileIDForMemBuffer(SB);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700298
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700299 if (mSourceMgr->getMainFileID().isInvalid()) {
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800300 mDiagnostics->Report(clang::diag::err_fe_error_reading) << InputFile;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700301 return false;
302 }
303 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700304}
305
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800306bool Slang::setInputSource(llvm::StringRef InputFile) {
307 mInputFileName = InputFile.str();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700308
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700309 mSourceMgr->clearIDTables();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700310
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800311 const clang::FileEntry *File = mFileMgr->getFile(InputFile);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700312 if (File)
313 mSourceMgr->createMainFileID(File);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700314
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700315 if (mSourceMgr->getMainFileID().isInvalid()) {
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800316 mDiagnostics->Report(clang::diag::err_fe_error_reading) << InputFile;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700317 return false;
318 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700319
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700320 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700321}
322
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800323bool Slang::setOutput(const char *OutputFile) {
Zonr Chang8c6d9b22010-10-07 18:01:19 +0800324 llvm::sys::Path OutputFilePath(OutputFile);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700325 std::string Error;
Zonr Change8c263a2010-10-12 00:35:29 +0800326 llvm::tool_output_file *OS = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700327
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800328 switch (mOT) {
Stephen Hinescc0efad2010-10-04 16:13:02 -0700329 case OT_Dependency:
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800330 case OT_Assembly:
331 case OT_LLVMAssembly: {
Zonr Change8c263a2010-10-12 00:35:29 +0800332 OS = OpenOutputFile(OutputFile, 0, &Error, mDiagnostics.getPtr());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700333 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700334 }
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800335 case OT_Nothing: {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700336 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700337 }
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800338 case OT_Object:
Stephen Hinescc0efad2010-10-04 16:13:02 -0700339 case OT_Bitcode: {
Zonr Change8c263a2010-10-12 00:35:29 +0800340 OS = OpenOutputFile(OutputFile,
341 llvm::raw_fd_ostream::F_Binary,
342 &Error,
343 mDiagnostics.getPtr());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700344 break;
345 }
Zonr Chang8c6d9b22010-10-07 18:01:19 +0800346 default: {
Stephen Hinescc0efad2010-10-04 16:13:02 -0700347 llvm_unreachable("Unknown compiler output type");
Zonr Chang8c6d9b22010-10-07 18:01:19 +0800348 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700349 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700350
Zonr Change8c263a2010-10-12 00:35:29 +0800351 if (!Error.empty())
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700352 return false;
Zonr Change8c263a2010-10-12 00:35:29 +0800353
354 mOS.reset(OS);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700355
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800356 mOutputFileName = OutputFile;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700357
358 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700359}
360
Stephen Hines0b7ef1a2010-10-07 16:36:59 -0700361bool Slang::setDepOutput(const char *OutputFile) {
Zonr Chang8c6d9b22010-10-07 18:01:19 +0800362 llvm::sys::Path OutputFilePath(OutputFile);
Stephen Hines0b7ef1a2010-10-07 16:36:59 -0700363 std::string Error;
Zonr Chang8c6d9b22010-10-07 18:01:19 +0800364
Zonr Change8c263a2010-10-12 00:35:29 +0800365 mDOS.reset(OpenOutputFile(OutputFile, 0, &Error, mDiagnostics.getPtr()));
366 if (!Error.empty() || (mDOS.get() == NULL))
Stephen Hines0b7ef1a2010-10-07 16:36:59 -0700367 return false;
Stephen Hines0b7ef1a2010-10-07 16:36:59 -0700368
369 mDepOutputFileName = OutputFile;
370
371 return true;
372}
373
Stephen Hinescc0efad2010-10-04 16:13:02 -0700374int Slang::generateDepFile() {
Zonr Changb2573012010-10-07 19:35:21 +0800375 if (mDiagnostics->getNumErrors() > 0)
Stephen Hinescc0efad2010-10-04 16:13:02 -0700376 return mDiagnostics->getNumErrors();
Stephen Hines0b7ef1a2010-10-07 16:36:59 -0700377 if (mDOS.get() == NULL)
Stephen Hinesf7de8522010-10-06 11:46:18 -0700378 return 1;
Stephen Hinescc0efad2010-10-04 16:13:02 -0700379
Zonr Change8c263a2010-10-12 00:35:29 +0800380 // Initialize options for generating dependency file
Stephen Hinescc0efad2010-10-04 16:13:02 -0700381 clang::DependencyOutputOptions DepOpts;
382 DepOpts.IncludeSystemHeaders = 1;
Stephen Hines0b7ef1a2010-10-07 16:36:59 -0700383 DepOpts.OutputFile = mDepOutputFileName;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700384 DepOpts.Targets = mAdditionalDepTargets;
Stephen Hinescc0efad2010-10-04 16:13:02 -0700385 DepOpts.Targets.push_back(mDepTargetBCFileName);
Stephen Hines4cc67fc2011-01-31 16:48:57 -0800386 for (std::vector<std::string>::const_iterator
387 I = mGeneratedFileNames.begin(), E = mGeneratedFileNames.end();
388 I != E;
389 I++) {
390 DepOpts.Targets.push_back(*I);
391 }
392 mGeneratedFileNames.clear();
Stephen Hinescc0efad2010-10-04 16:13:02 -0700393
Zonr Change8c263a2010-10-12 00:35:29 +0800394 // Per-compilation needed initialization
Stephen Hinescc0efad2010-10-04 16:13:02 -0700395 createPreprocessor();
396 AttachDependencyFileGen(*mPP.get(), DepOpts);
397
Zonr Change8c263a2010-10-12 00:35:29 +0800398 // Inform the diagnostic client we are processing a source file
Stephen Hinescc0efad2010-10-04 16:13:02 -0700399 mDiagClient->BeginSourceFile(LangOpts, mPP.get());
400
Zonr Change8c263a2010-10-12 00:35:29 +0800401 // Go through the source file (no operations necessary)
Stephen Hinescc0efad2010-10-04 16:13:02 -0700402 clang::Token Tok;
403 mPP->EnterMainSourceFile();
404 do {
405 mPP->Lex(Tok);
406 } while (Tok.isNot(clang::tok::eof));
407
408 mPP->EndSourceFile();
409
Zonr Change8c263a2010-10-12 00:35:29 +0800410 // Declare success if no error
411 if (mDiagnostics->getNumErrors() == 0)
412 mDOS->keep();
413
414 // Clean up after compilation
Stephen Hinescc0efad2010-10-04 16:13:02 -0700415 mPP.reset();
Zonr Change8c263a2010-10-12 00:35:29 +0800416 mDOS.reset();
Stephen Hinescc0efad2010-10-04 16:13:02 -0700417
418 return mDiagnostics->getNumErrors();
419}
420
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700421int Slang::compile() {
Stephen Hinesf7de8522010-10-06 11:46:18 -0700422 if (mDiagnostics->getNumErrors() > 0)
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700423 return mDiagnostics->getNumErrors();
Stephen Hinesf7de8522010-10-06 11:46:18 -0700424 if (mOS.get() == NULL)
425 return 1;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700426
427 // Here is per-compilation needed initialization
428 createPreprocessor();
429 createASTContext();
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800430
Zonr Change8c263a2010-10-12 00:35:29 +0800431 mBackend.reset(createBackend(CodeGenOpts, mOS.get(), mOT));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700432
433 // Inform the diagnostic client we are processing a source file
434 mDiagClient->BeginSourceFile(LangOpts, mPP.get());
435
436 // The core of the slang compiler
437 ParseAST(*mPP, mBackend.get(), *mASTContext);
438
Zonr Change8c263a2010-10-12 00:35:29 +0800439 // Inform the diagnostic client we are done with previous source file
440 mDiagClient->EndSourceFile();
441
442 // Declare success if no error
443 if (mDiagnostics->getNumErrors() == 0)
444 mOS->keep();
445
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800446 // The compilation ended, clear
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700447 mBackend.reset();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700448 mASTContext.reset();
449 mPP.reset();
Zonr Change8c263a2010-10-12 00:35:29 +0800450 mOS.reset();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700451
452 return mDiagnostics->getNumErrors();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700453}
454
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800455void Slang::reset() {
456 mDiagnostics->Reset();
457 mDiagClient->reset();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700458 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700459}
460
461Slang::~Slang() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700462 llvm::llvm_shutdown();
463 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700464}
Stephen Hinese639eb52010-11-08 19:27:20 -0800465
466} // namespace slang