blob: 7e39d29c49a1d2b5e95be6887ebee68d7a8b21d0 [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
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080063#include "slang_backend.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080064#include "slang_utils.h"
Shih-wei Liaob81c6a42010-10-10 14:15:00 -070065
Zonr Chang08df36e2010-10-07 18:50:42 +080066namespace {
Zonr Chang08df36e2010-10-07 18:50:42 +080067
Stephen Hinese639eb52010-11-08 19:27:20 -080068struct ForceSlangLinking {
69 ForceSlangLinking() {
70 // We must reference the functions in such a way that compilers will not
71 // delete it all as dead code, even with whole program optimization,
72 // yet is effectively a NO-OP. As the compiler isn't smart enough
73 // to know that getenv() never returns -1, this will do the job.
74 if (std::getenv("bar") != reinterpret_cast<char*>(-1))
75 return;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -070076
Stephen Hinese639eb52010-11-08 19:27:20 -080077 // llvm-rs-link needs following functions existing in libslang.
78 llvm::ParseBitcodeFile(NULL, llvm::getGlobalContext(), NULL);
79 llvm::Linker::LinkModules(NULL, NULL, NULL);
Zonr Chang08df36e2010-10-07 18:50:42 +080080
Stephen Hinese639eb52010-11-08 19:27:20 -080081 // llvm-rs-cc need this.
82 new clang::TextDiagnosticPrinter(llvm::errs(),
83 clang::DiagnosticOptions());
84 }
85} ForceSlangLinking;
86
87} // namespace
88
89namespace slang {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070090
Shih-wei Liao462aefd2010-06-04 15:32:04 -070091#if defined(__arm__)
92# define DEFAULT_TARGET_TRIPLE_STRING "armv7-none-linux-gnueabi"
93#elif defined(__x86_64__)
94# define DEFAULT_TARGET_TRIPLE_STRING "x86_64-unknown-linux"
95#else
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070096// let's use x86 as default target
97# define DEFAULT_TARGET_TRIPLE_STRING "i686-unknown-linux"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070098#endif
99
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700100bool Slang::GlobalInitialized = false;
101
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700102// Language option (define the language feature for compiler such as C99)
103clang::LangOptions Slang::LangOpts;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700104
zonr6315f762010-10-05 15:35:14 +0800105// Code generation option for the compiler
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700106clang::CodeGenOptions Slang::CodeGenOpts;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700107
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700108// The named of metadata node that pragma resides (should be synced with
109// bcc.cpp)
Shih-wei Liaof52a6202010-09-10 17:40:53 -0700110const llvm::StringRef Slang::PragmaMetadataName = "#pragma";
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700111
Zonr Change8c263a2010-10-12 00:35:29 +0800112static inline llvm::tool_output_file *OpenOutputFile(const char *OutputFile,
113 unsigned Flags,
114 std::string* Error,
115 clang::Diagnostic* Diag) {
116 assert((OutputFile != NULL) && (Error != NULL) && (Diag != NULL) &&
117 "Invalid parameter!");
118
119 llvm::sys::Path OutputFilePath(OutputFile);
120
121 if (SlangUtils::CreateDirectoryWithParents(OutputFilePath.getDirname(),
122 Error)) {
123 llvm::tool_output_file *F =
124 new llvm::tool_output_file(OutputFile, *Error, Flags);
125 if (F != NULL)
126 return F;
127 }
128
129 // Report error here.
130 Diag->Report(clang::diag::err_fe_error_opening) << OutputFile << *Error;
131
132 return NULL;
133}
134
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700135void Slang::GlobalInitialization() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700136 if (!GlobalInitialized) {
137 // We only support x86, x64 and ARM target
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700138
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700139 // For ARM
140 LLVMInitializeARMTargetInfo();
141 LLVMInitializeARMTarget();
142 LLVMInitializeARMAsmPrinter();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700143
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700144 // For x86 and x64
145 LLVMInitializeX86TargetInfo();
146 LLVMInitializeX86Target();
147 LLVMInitializeX86AsmPrinter();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700148
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800149 // Please refer to include/clang/Basic/LangOptions.h to setup
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700150 // the options.
151 LangOpts.RTTI = 0; // Turn off the RTTI information support
152 LangOpts.NeXTRuntime = 0; // Turn off the NeXT runtime uses
153 LangOpts.Bool = 1; // Turn on 'bool', 'true', 'false' keywords
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700154
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700155 CodeGenOpts.OptimizationLevel = 3; /* -O3 */
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700156
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700157 GlobalInitialized = true;
158 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700159
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700160 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700161}
162
163void Slang::LLVMErrorHandler(void *UserData, const std::string &Message) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700164 clang::Diagnostic* Diags = static_cast<clang::Diagnostic*>(UserData);
165 Diags->Report(clang::diag::err_fe_error_backend) << Message;
166 exit(1);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700167}
168
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800169void Slang::createDiagnostic() {
170 mDiagnostics =
171 llvm::IntrusiveRefCntPtr<clang::Diagnostic>(new clang::Diagnostic());
172 mDiagClient = new DiagnosticBuffer();
173 // This takes the ownership of mDiagClient.
174 mDiagnostics->setClient(mDiagClient);
Zonr Chang641558f2010-10-12 21:07:06 +0800175 initDiagnostic();
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800176 return;
177}
178
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700179void Slang::createTarget(const std::string &Triple, const std::string &CPU,
180 const std::vector<std::string> &Features) {
181 if (!Triple.empty())
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700182 mTargetOpts.Triple = Triple;
183 else
184 mTargetOpts.Triple = DEFAULT_TARGET_TRIPLE_STRING;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700185
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700186 if (!CPU.empty())
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700187 mTargetOpts.CPU = CPU;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700188
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700189 if (!Features.empty())
190 mTargetOpts.Features = Features;
191
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700192 mTarget.reset(clang::TargetInfo::CreateTargetInfo(*mDiagnostics,
193 mTargetOpts));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700194
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700195 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700196}
197
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800198void Slang::createFileManager() {
199 mFileMgr.reset(new clang::FileManager());
200}
201
202void Slang::createSourceManager() {
203 mSourceMgr.reset(new clang::SourceManager(*mDiagnostics));
204 return;
205}
206
Shih-wei Liao68e8e9f2010-07-18 18:46:49 -0700207void Slang::createPreprocessor() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700208 // Default only search header file in current dir
209 clang::HeaderSearch *HS = new clang::HeaderSearch(*mFileMgr);
Shih-wei Liao68e8e9f2010-07-18 18:46:49 -0700210
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700211 mPP.reset(new clang::Preprocessor(*mDiagnostics,
212 LangOpts,
213 *mTarget,
214 *mSourceMgr,
215 *HS,
216 NULL,
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800217 /* OwnsHeaderSearch = */true));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700218 // Initialize the prepocessor
Shih-wei Liao68e8e9f2010-07-18 18:46:49 -0700219 mPragmas.clear();
Shih-wei Liaof52a6202010-09-10 17:40:53 -0700220 mPP->AddPragmaHandler(new PragmaRecorder(mPragmas));
Shih-wei Liao68e8e9f2010-07-18 18:46:49 -0700221
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700222 std::vector<clang::DirectoryLookup> SearchList;
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800223 for (unsigned i = 0, e = mIncludePaths.size(); i != e; i++) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700224 if (const clang::DirectoryEntry *DE =
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800225 mFileMgr->getDirectory(mIncludePaths[i])) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700226 SearchList.push_back(clang::DirectoryLookup(DE,
227 clang::SrcMgr::C_System,
228 false,
229 false));
230 }
Shih-wei Liao90898282010-07-19 18:38:57 -0700231 }
232
233 HS->SetSearchPaths(SearchList, 1, false);
234
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800235 initPreprocessor();
Shih-wei Liao68e8e9f2010-07-18 18:46:49 -0700236 return;
237}
238
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800239void Slang::createASTContext() {
240 mASTContext.reset(new clang::ASTContext(LangOpts,
241 *mSourceMgr,
242 *mTarget,
243 mPP->getIdentifierTable(),
244 mPP->getSelectorTable(),
245 mPP->getBuiltinInfo(),
246 /* size_reserve = */0));
247 initASTContext();
248 return;
249}
250
251clang::ASTConsumer
252*Slang::createBackend(const clang::CodeGenOptions& CodeGenOpts,
253 llvm::raw_ostream *OS,
254 OutputType OT) {
Stephen Hinese639eb52010-11-08 19:27:20 -0800255 return new Backend(mDiagnostics.getPtr(),
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800256 CodeGenOpts,
257 mTargetOpts,
258 mPragmas,
259 OS,
260 OT);
261}
262
Zonr Chang641558f2010-10-12 21:07:06 +0800263Slang::Slang() : mInitialized(false), mDiagClient(NULL), mOT(OT_Default) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700264 GlobalInitialization();
Zonr Chang641558f2010-10-12 21:07:06 +0800265 return;
266}
267
268void Slang::init(const std::string &Triple, const std::string &CPU,
269 const std::vector<std::string> &Features) {
270 if (mInitialized)
271 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700272
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700273 createDiagnostic();
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800274 llvm::install_fatal_error_handler(LLVMErrorHandler, mDiagnostics.getPtr());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700275
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700276 createTarget(Triple, CPU, Features);
277 createFileManager();
278 createSourceManager();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700279
Zonr Chang641558f2010-10-12 21:07:06 +0800280 mInitialized = true;
281
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700282 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700283}
284
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800285bool Slang::setInputSource(llvm::StringRef InputFile,
286 const char *Text,
287 size_t TextLength) {
288 mInputFileName = InputFile.str();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700289
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700290 // Reset the ID tables if we are reusing the SourceManager
291 mSourceMgr->clearIDTables();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700292
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700293 // Load the source
zonr6315f762010-10-05 15:35:14 +0800294 llvm::MemoryBuffer *SB =
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800295 llvm::MemoryBuffer::getMemBuffer(Text, Text + TextLength);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700296 mSourceMgr->createMainFileIDForMemBuffer(SB);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700297
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700298 if (mSourceMgr->getMainFileID().isInvalid()) {
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800299 mDiagnostics->Report(clang::diag::err_fe_error_reading) << InputFile;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700300 return false;
301 }
302 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700303}
304
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800305bool Slang::setInputSource(llvm::StringRef InputFile) {
306 mInputFileName = InputFile.str();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700307
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700308 mSourceMgr->clearIDTables();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700309
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800310 const clang::FileEntry *File = mFileMgr->getFile(InputFile);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700311 if (File)
312 mSourceMgr->createMainFileID(File);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700313
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700314 if (mSourceMgr->getMainFileID().isInvalid()) {
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800315 mDiagnostics->Report(clang::diag::err_fe_error_reading) << InputFile;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700316 return false;
317 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700318
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700319 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700320}
321
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800322bool Slang::setOutput(const char *OutputFile) {
Zonr Chang8c6d9b22010-10-07 18:01:19 +0800323 llvm::sys::Path OutputFilePath(OutputFile);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700324 std::string Error;
Zonr Change8c263a2010-10-12 00:35:29 +0800325 llvm::tool_output_file *OS = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700326
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800327 switch (mOT) {
Stephen Hinescc0efad2010-10-04 16:13:02 -0700328 case OT_Dependency:
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800329 case OT_Assembly:
330 case OT_LLVMAssembly: {
Zonr Change8c263a2010-10-12 00:35:29 +0800331 OS = OpenOutputFile(OutputFile, 0, &Error, mDiagnostics.getPtr());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700332 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700333 }
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800334 case OT_Nothing: {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700335 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700336 }
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800337 case OT_Object:
Stephen Hinescc0efad2010-10-04 16:13:02 -0700338 case OT_Bitcode: {
Zonr Change8c263a2010-10-12 00:35:29 +0800339 OS = OpenOutputFile(OutputFile,
340 llvm::raw_fd_ostream::F_Binary,
341 &Error,
342 mDiagnostics.getPtr());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700343 break;
344 }
Zonr Chang8c6d9b22010-10-07 18:01:19 +0800345 default: {
Stephen Hinescc0efad2010-10-04 16:13:02 -0700346 llvm_unreachable("Unknown compiler output type");
Zonr Chang8c6d9b22010-10-07 18:01:19 +0800347 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700348 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700349
Zonr Change8c263a2010-10-12 00:35:29 +0800350 if (!Error.empty())
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700351 return false;
Zonr Change8c263a2010-10-12 00:35:29 +0800352
353 mOS.reset(OS);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700354
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800355 mOutputFileName = OutputFile;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700356
357 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700358}
359
Stephen Hines0b7ef1a2010-10-07 16:36:59 -0700360bool Slang::setDepOutput(const char *OutputFile) {
Zonr Chang8c6d9b22010-10-07 18:01:19 +0800361 llvm::sys::Path OutputFilePath(OutputFile);
Stephen Hines0b7ef1a2010-10-07 16:36:59 -0700362 std::string Error;
Zonr Chang8c6d9b22010-10-07 18:01:19 +0800363
Zonr Change8c263a2010-10-12 00:35:29 +0800364 mDOS.reset(OpenOutputFile(OutputFile, 0, &Error, mDiagnostics.getPtr()));
365 if (!Error.empty() || (mDOS.get() == NULL))
Stephen Hines0b7ef1a2010-10-07 16:36:59 -0700366 return false;
Stephen Hines0b7ef1a2010-10-07 16:36:59 -0700367
368 mDepOutputFileName = OutputFile;
369
370 return true;
371}
372
Stephen Hinescc0efad2010-10-04 16:13:02 -0700373int Slang::generateDepFile() {
Zonr Changb2573012010-10-07 19:35:21 +0800374 if (mDiagnostics->getNumErrors() > 0)
Stephen Hinescc0efad2010-10-04 16:13:02 -0700375 return mDiagnostics->getNumErrors();
Stephen Hines0b7ef1a2010-10-07 16:36:59 -0700376 if (mDOS.get() == NULL)
Stephen Hinesf7de8522010-10-06 11:46:18 -0700377 return 1;
Stephen Hinescc0efad2010-10-04 16:13:02 -0700378
Zonr Change8c263a2010-10-12 00:35:29 +0800379 // Initialize options for generating dependency file
Stephen Hinescc0efad2010-10-04 16:13:02 -0700380 clang::DependencyOutputOptions DepOpts;
381 DepOpts.IncludeSystemHeaders = 1;
Stephen Hines0b7ef1a2010-10-07 16:36:59 -0700382 DepOpts.OutputFile = mDepOutputFileName;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700383 DepOpts.Targets = mAdditionalDepTargets;
Stephen Hinescc0efad2010-10-04 16:13:02 -0700384 DepOpts.Targets.push_back(mDepTargetBCFileName);
385
Zonr Change8c263a2010-10-12 00:35:29 +0800386 // Per-compilation needed initialization
Stephen Hinescc0efad2010-10-04 16:13:02 -0700387 createPreprocessor();
388 AttachDependencyFileGen(*mPP.get(), DepOpts);
389
Zonr Change8c263a2010-10-12 00:35:29 +0800390 // Inform the diagnostic client we are processing a source file
Stephen Hinescc0efad2010-10-04 16:13:02 -0700391 mDiagClient->BeginSourceFile(LangOpts, mPP.get());
392
Zonr Change8c263a2010-10-12 00:35:29 +0800393 // Go through the source file (no operations necessary)
Stephen Hinescc0efad2010-10-04 16:13:02 -0700394 clang::Token Tok;
395 mPP->EnterMainSourceFile();
396 do {
397 mPP->Lex(Tok);
398 } while (Tok.isNot(clang::tok::eof));
399
400 mPP->EndSourceFile();
401
Zonr Change8c263a2010-10-12 00:35:29 +0800402 // Declare success if no error
403 if (mDiagnostics->getNumErrors() == 0)
404 mDOS->keep();
405
406 // Clean up after compilation
Stephen Hinescc0efad2010-10-04 16:13:02 -0700407 mPP.reset();
Zonr Change8c263a2010-10-12 00:35:29 +0800408 mDOS.reset();
Stephen Hinescc0efad2010-10-04 16:13:02 -0700409
410 return mDiagnostics->getNumErrors();
411}
412
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700413int Slang::compile() {
Stephen Hinesf7de8522010-10-06 11:46:18 -0700414 if (mDiagnostics->getNumErrors() > 0)
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700415 return mDiagnostics->getNumErrors();
Stephen Hinesf7de8522010-10-06 11:46:18 -0700416 if (mOS.get() == NULL)
417 return 1;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700418
419 // Here is per-compilation needed initialization
420 createPreprocessor();
421 createASTContext();
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800422
Zonr Change8c263a2010-10-12 00:35:29 +0800423 mBackend.reset(createBackend(CodeGenOpts, mOS.get(), mOT));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700424
425 // Inform the diagnostic client we are processing a source file
426 mDiagClient->BeginSourceFile(LangOpts, mPP.get());
427
428 // The core of the slang compiler
429 ParseAST(*mPP, mBackend.get(), *mASTContext);
430
Zonr Change8c263a2010-10-12 00:35:29 +0800431 // Inform the diagnostic client we are done with previous source file
432 mDiagClient->EndSourceFile();
433
434 // Declare success if no error
435 if (mDiagnostics->getNumErrors() == 0)
436 mOS->keep();
437
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800438 // The compilation ended, clear
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700439 mBackend.reset();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700440 mASTContext.reset();
441 mPP.reset();
Zonr Change8c263a2010-10-12 00:35:29 +0800442 mOS.reset();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700443
444 return mDiagnostics->getNumErrors();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700445}
446
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800447void Slang::reset() {
448 mDiagnostics->Reset();
449 mDiagClient->reset();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700450 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700451}
452
453Slang::~Slang() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700454 llvm::llvm_shutdown();
455 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700456}
Stephen Hinese639eb52010-11-08 19:27:20 -0800457
458} // namespace slang