blob: 79b05013565bb4fdf6740c5350393cd8424ab638 [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
Loganbe274822011-02-16 22:02:54 +080027#include "clang/Basic/DiagnosticIDs.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080028#include "clang/Basic/FileManager.h"
Shih-wei Liaodf5bcce2011-02-28 18:39:23 -080029#include "clang/Basic/FileSystemOptions.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080030#include "clang/Basic/LangOptions.h"
31#include "clang/Basic/SourceManager.h"
32#include "clang/Basic/TargetInfo.h"
33#include "clang/Basic/TargetOptions.h"
34
35#include "clang/Frontend/CodeGenOptions.h"
36#include "clang/Frontend/DiagnosticOptions.h"
37#include "clang/Frontend/DependencyOutputOptions.h"
38#include "clang/Frontend/FrontendDiagnostic.h"
39#include "clang/Frontend/TextDiagnosticPrinter.h"
40#include "clang/Frontend/Utils.h"
41
42#include "clang/Lex/Preprocessor.h"
43#include "clang/Lex/HeaderSearch.h"
44
45#include "clang/Parse/ParseAST.h"
46
Loganbe274822011-02-16 22:02:54 +080047#include "llvm/ADT/IntrusiveRefCntPtr.h"
48
Stephen Hinese639eb52010-11-08 19:27:20 -080049#include "llvm/Bitcode/ReaderWriter.h"
50
51// More force linking
52#include "llvm/Linker.h"
53
Zonr Chang08df36e2010-10-07 18:50:42 +080054// Force linking all passes/vmcore stuffs to libslang.so
55#include "llvm/LinkAllPasses.h"
56#include "llvm/LinkAllVMCore.h"
57
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080058#include "llvm/Support/raw_ostream.h"
zonr6315f762010-10-05 15:35:14 +080059#include "llvm/Support/MemoryBuffer.h"
60#include "llvm/Support/ErrorHandling.h"
61#include "llvm/Support/ManagedStatic.h"
Shih-wei Liaodf5bcce2011-02-28 18:39:23 -080062#include "llvm/Support/ToolOutputFile.h"
Loganbe274822011-02-16 22:02:54 +080063#include "llvm/Support/Path.h"
zonr6315f762010-10-05 15:35:14 +080064
Stephen Hinese639eb52010-11-08 19:27:20 -080065#include "llvm/Target/TargetSelect.h"
Stephen Hinescc0efad2010-10-04 16:13:02 -070066
Stephen Hines6e6578a2011-02-07 18:05:48 -080067#include "slang_assert.h"
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080068#include "slang_backend.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080069#include "slang_utils.h"
Shih-wei Liaob81c6a42010-10-10 14:15:00 -070070
Zonr Chang08df36e2010-10-07 18:50:42 +080071namespace {
Zonr Chang08df36e2010-10-07 18:50:42 +080072
Stephen Hinese639eb52010-11-08 19:27:20 -080073struct ForceSlangLinking {
74 ForceSlangLinking() {
75 // We must reference the functions in such a way that compilers will not
76 // delete it all as dead code, even with whole program optimization,
77 // yet is effectively a NO-OP. As the compiler isn't smart enough
78 // to know that getenv() never returns -1, this will do the job.
79 if (std::getenv("bar") != reinterpret_cast<char*>(-1))
80 return;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -070081
Stephen Hinese639eb52010-11-08 19:27:20 -080082 // llvm-rs-link needs following functions existing in libslang.
83 llvm::ParseBitcodeFile(NULL, llvm::getGlobalContext(), NULL);
84 llvm::Linker::LinkModules(NULL, NULL, NULL);
Zonr Chang08df36e2010-10-07 18:50:42 +080085
Stephen Hinese639eb52010-11-08 19:27:20 -080086 // llvm-rs-cc need this.
87 new clang::TextDiagnosticPrinter(llvm::errs(),
88 clang::DiagnosticOptions());
89 }
90} ForceSlangLinking;
91
92} // namespace
93
94namespace slang {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070095
Shih-wei Liao462aefd2010-06-04 15:32:04 -070096#if defined(__arm__)
97# define DEFAULT_TARGET_TRIPLE_STRING "armv7-none-linux-gnueabi"
98#elif defined(__x86_64__)
99# define DEFAULT_TARGET_TRIPLE_STRING "x86_64-unknown-linux"
100#else
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700101// let's use x86 as default target
102# define DEFAULT_TARGET_TRIPLE_STRING "i686-unknown-linux"
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700103#endif
104
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700105bool Slang::GlobalInitialized = false;
106
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700107// Language option (define the language feature for compiler such as C99)
108clang::LangOptions Slang::LangOpts;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700109
zonr6315f762010-10-05 15:35:14 +0800110// Code generation option for the compiler
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700111clang::CodeGenOptions Slang::CodeGenOpts;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700112
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700113// The named of metadata node that pragma resides (should be synced with
114// bcc.cpp)
Shih-wei Liaof52a6202010-09-10 17:40:53 -0700115const llvm::StringRef Slang::PragmaMetadataName = "#pragma";
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700116
Zonr Change8c263a2010-10-12 00:35:29 +0800117static inline llvm::tool_output_file *OpenOutputFile(const char *OutputFile,
118 unsigned Flags,
119 std::string* Error,
120 clang::Diagnostic* Diag) {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800121 slangAssert((OutputFile != NULL) && (Error != NULL) && (Diag != NULL) &&
122 "Invalid parameter!");
Zonr Change8c263a2010-10-12 00:35:29 +0800123
Logan Chien6f4e0a92011-03-10 01:10:25 +0800124 if (SlangUtils::CreateDirectoryWithParents(
125 llvm::sys::path::parent_path(OutputFile), Error)) {
Zonr Change8c263a2010-10-12 00:35:29 +0800126 llvm::tool_output_file *F =
127 new llvm::tool_output_file(OutputFile, *Error, Flags);
128 if (F != NULL)
129 return F;
130 }
131
132 // Report error here.
133 Diag->Report(clang::diag::err_fe_error_opening) << OutputFile << *Error;
134
135 return NULL;
136}
137
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700138void Slang::GlobalInitialization() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700139 if (!GlobalInitialized) {
140 // We only support x86, x64 and ARM target
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700141
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700142 // For ARM
143 LLVMInitializeARMTargetInfo();
144 LLVMInitializeARMTarget();
145 LLVMInitializeARMAsmPrinter();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700146
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700147 // For x86 and x64
148 LLVMInitializeX86TargetInfo();
149 LLVMInitializeX86Target();
150 LLVMInitializeX86AsmPrinter();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700151
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800152 // Please refer to include/clang/Basic/LangOptions.h to setup
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700153 // the options.
154 LangOpts.RTTI = 0; // Turn off the RTTI information support
155 LangOpts.NeXTRuntime = 0; // Turn off the NeXT runtime uses
Shih-wei Liao245eba12011-01-19 02:14:07 -0800156 LangOpts.C99 = 1;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700157
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700158 CodeGenOpts.OptimizationLevel = 3; /* -O3 */
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700159
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700160 GlobalInitialized = true;
161 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700162
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700163 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700164}
165
166void Slang::LLVMErrorHandler(void *UserData, const std::string &Message) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700167 clang::Diagnostic* Diags = static_cast<clang::Diagnostic*>(UserData);
168 Diags->Report(clang::diag::err_fe_error_backend) << Message;
169 exit(1);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700170}
171
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800172void Slang::createDiagnostic() {
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800173 mDiagClient = new DiagnosticBuffer();
Loganbe274822011-02-16 22:02:54 +0800174 mDiagIDs = new clang::DiagnosticIDs();
175 mDiagnostics = new clang::Diagnostic(mDiagIDs, mDiagClient, true);
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() {
Shih-wei Liaodf5bcce2011-02-28 18:39:23 -0800200 mFileSysOpt.reset(new clang::FileSystemOptions());
Loganbe274822011-02-16 22:02:54 +0800201 mFileMgr.reset(new clang::FileManager(*mFileSysOpt));
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800202}
203
204void Slang::createSourceManager() {
Loganbe274822011-02-16 22:02:54 +0800205 mSourceMgr.reset(new clang::SourceManager(*mDiagnostics, *mFileMgr));
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800206 return;
207}
208
Shih-wei Liao68e8e9f2010-07-18 18:46:49 -0700209void Slang::createPreprocessor() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700210 // Default only search header file in current dir
Loganbe274822011-02-16 22:02:54 +0800211 clang::HeaderSearch *HS = new clang::HeaderSearch(*mFileMgr);
Shih-wei Liao68e8e9f2010-07-18 18:46:49 -0700212
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700213 mPP.reset(new clang::Preprocessor(*mDiagnostics,
214 LangOpts,
215 *mTarget,
216 *mSourceMgr,
217 *HS,
218 NULL,
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800219 /* OwnsHeaderSearch = */true));
Stephen Hines3fd0a942011-01-18 12:27:39 -0800220 // Initialize the preprocessor
Shih-wei Liao68e8e9f2010-07-18 18:46:49 -0700221 mPragmas.clear();
Stephen Hines3fd0a942011-01-18 12:27:39 -0800222 mPP->AddPragmaHandler(new PragmaRecorder(&mPragmas));
Shih-wei Liao68e8e9f2010-07-18 18:46:49 -0700223
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700224 std::vector<clang::DirectoryLookup> SearchList;
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800225 for (unsigned i = 0, e = mIncludePaths.size(); i != e; i++) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700226 if (const clang::DirectoryEntry *DE =
Loganbe274822011-02-16 22:02:54 +0800227 mFileMgr->getDirectory(mIncludePaths[i])) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700228 SearchList.push_back(clang::DirectoryLookup(DE,
229 clang::SrcMgr::C_System,
230 false,
231 false));
232 }
Shih-wei Liao90898282010-07-19 18:38:57 -0700233 }
234
Shih-wei Liaofcc654a2011-06-22 04:47:33 -0700235 HS->SetSearchPaths(SearchList,
236 /* angledDirIdx = */1,
237 /* systemDixIdx = */1,
238 /* noCurDirSearch = */false);
Shih-wei Liao90898282010-07-19 18:38:57 -0700239
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800240 initPreprocessor();
Shih-wei Liao68e8e9f2010-07-18 18:46:49 -0700241 return;
242}
243
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800244void Slang::createASTContext() {
245 mASTContext.reset(new clang::ASTContext(LangOpts,
246 *mSourceMgr,
247 *mTarget,
248 mPP->getIdentifierTable(),
249 mPP->getSelectorTable(),
250 mPP->getBuiltinInfo(),
251 /* size_reserve = */0));
252 initASTContext();
253 return;
254}
255
256clang::ASTConsumer
257*Slang::createBackend(const clang::CodeGenOptions& CodeGenOpts,
258 llvm::raw_ostream *OS,
259 OutputType OT) {
Stephen Hinese639eb52010-11-08 19:27:20 -0800260 return new Backend(mDiagnostics.getPtr(),
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800261 CodeGenOpts,
262 mTargetOpts,
Stephen Hines3fd0a942011-01-18 12:27:39 -0800263 &mPragmas,
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800264 OS,
265 OT);
266}
267
Zonr Chang641558f2010-10-12 21:07:06 +0800268Slang::Slang() : mInitialized(false), mDiagClient(NULL), mOT(OT_Default) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700269 GlobalInitialization();
Zonr Chang641558f2010-10-12 21:07:06 +0800270 return;
271}
272
273void Slang::init(const std::string &Triple, const std::string &CPU,
274 const std::vector<std::string> &Features) {
275 if (mInitialized)
276 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700277
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700278 createDiagnostic();
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800279 llvm::install_fatal_error_handler(LLVMErrorHandler, mDiagnostics.getPtr());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700280
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700281 createTarget(Triple, CPU, Features);
282 createFileManager();
283 createSourceManager();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700284
Zonr Chang641558f2010-10-12 21:07:06 +0800285 mInitialized = true;
286
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700287 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700288}
289
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800290bool Slang::setInputSource(llvm::StringRef InputFile,
291 const char *Text,
292 size_t TextLength) {
293 mInputFileName = InputFile.str();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700294
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700295 // Reset the ID tables if we are reusing the SourceManager
296 mSourceMgr->clearIDTables();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700297
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700298 // Load the source
zonr6315f762010-10-05 15:35:14 +0800299 llvm::MemoryBuffer *SB =
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800300 llvm::MemoryBuffer::getMemBuffer(Text, Text + TextLength);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700301 mSourceMgr->createMainFileIDForMemBuffer(SB);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700302
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700303 if (mSourceMgr->getMainFileID().isInvalid()) {
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800304 mDiagnostics->Report(clang::diag::err_fe_error_reading) << InputFile;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700305 return false;
306 }
307 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700308}
309
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800310bool Slang::setInputSource(llvm::StringRef InputFile) {
311 mInputFileName = InputFile.str();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700312
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700313 mSourceMgr->clearIDTables();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700314
Loganbe274822011-02-16 22:02:54 +0800315 const clang::FileEntry *File = mFileMgr->getFile(InputFile);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700316 if (File)
317 mSourceMgr->createMainFileID(File);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700318
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700319 if (mSourceMgr->getMainFileID().isInvalid()) {
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800320 mDiagnostics->Report(clang::diag::err_fe_error_reading) << InputFile;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700321 return false;
322 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700323
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700324 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700325}
326
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800327bool Slang::setOutput(const char *OutputFile) {
Zonr Chang8c6d9b22010-10-07 18:01:19 +0800328 llvm::sys::Path OutputFilePath(OutputFile);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700329 std::string Error;
Zonr Change8c263a2010-10-12 00:35:29 +0800330 llvm::tool_output_file *OS = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700331
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800332 switch (mOT) {
Stephen Hinescc0efad2010-10-04 16:13:02 -0700333 case OT_Dependency:
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800334 case OT_Assembly:
335 case OT_LLVMAssembly: {
Zonr Change8c263a2010-10-12 00:35:29 +0800336 OS = OpenOutputFile(OutputFile, 0, &Error, mDiagnostics.getPtr());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700337 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700338 }
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800339 case OT_Nothing: {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700340 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700341 }
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800342 case OT_Object:
Stephen Hinescc0efad2010-10-04 16:13:02 -0700343 case OT_Bitcode: {
Zonr Change8c263a2010-10-12 00:35:29 +0800344 OS = OpenOutputFile(OutputFile,
345 llvm::raw_fd_ostream::F_Binary,
346 &Error,
347 mDiagnostics.getPtr());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700348 break;
349 }
Zonr Chang8c6d9b22010-10-07 18:01:19 +0800350 default: {
Stephen Hinescc0efad2010-10-04 16:13:02 -0700351 llvm_unreachable("Unknown compiler output type");
Zonr Chang8c6d9b22010-10-07 18:01:19 +0800352 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700353 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700354
Zonr Change8c263a2010-10-12 00:35:29 +0800355 if (!Error.empty())
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700356 return false;
Zonr Change8c263a2010-10-12 00:35:29 +0800357
358 mOS.reset(OS);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700359
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800360 mOutputFileName = OutputFile;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700361
362 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700363}
364
Stephen Hines0b7ef1a2010-10-07 16:36:59 -0700365bool Slang::setDepOutput(const char *OutputFile) {
Zonr Chang8c6d9b22010-10-07 18:01:19 +0800366 llvm::sys::Path OutputFilePath(OutputFile);
Stephen Hines0b7ef1a2010-10-07 16:36:59 -0700367 std::string Error;
Zonr Chang8c6d9b22010-10-07 18:01:19 +0800368
Zonr Change8c263a2010-10-12 00:35:29 +0800369 mDOS.reset(OpenOutputFile(OutputFile, 0, &Error, mDiagnostics.getPtr()));
370 if (!Error.empty() || (mDOS.get() == NULL))
Stephen Hines0b7ef1a2010-10-07 16:36:59 -0700371 return false;
Stephen Hines0b7ef1a2010-10-07 16:36:59 -0700372
373 mDepOutputFileName = OutputFile;
374
375 return true;
376}
377
Stephen Hinescc0efad2010-10-04 16:13:02 -0700378int Slang::generateDepFile() {
Loganbe274822011-02-16 22:02:54 +0800379 if (mDiagnostics->hasErrorOccurred())
380 return 1;
Stephen Hines0b7ef1a2010-10-07 16:36:59 -0700381 if (mDOS.get() == NULL)
Stephen Hinesf7de8522010-10-06 11:46:18 -0700382 return 1;
Stephen Hinescc0efad2010-10-04 16:13:02 -0700383
Zonr Change8c263a2010-10-12 00:35:29 +0800384 // Initialize options for generating dependency file
Stephen Hinescc0efad2010-10-04 16:13:02 -0700385 clang::DependencyOutputOptions DepOpts;
386 DepOpts.IncludeSystemHeaders = 1;
Stephen Hines0b7ef1a2010-10-07 16:36:59 -0700387 DepOpts.OutputFile = mDepOutputFileName;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700388 DepOpts.Targets = mAdditionalDepTargets;
Stephen Hinescc0efad2010-10-04 16:13:02 -0700389 DepOpts.Targets.push_back(mDepTargetBCFileName);
Stephen Hines4cc67fc2011-01-31 16:48:57 -0800390 for (std::vector<std::string>::const_iterator
391 I = mGeneratedFileNames.begin(), E = mGeneratedFileNames.end();
392 I != E;
393 I++) {
394 DepOpts.Targets.push_back(*I);
395 }
396 mGeneratedFileNames.clear();
Stephen Hinescc0efad2010-10-04 16:13:02 -0700397
Zonr Change8c263a2010-10-12 00:35:29 +0800398 // Per-compilation needed initialization
Stephen Hinescc0efad2010-10-04 16:13:02 -0700399 createPreprocessor();
400 AttachDependencyFileGen(*mPP.get(), DepOpts);
401
Zonr Change8c263a2010-10-12 00:35:29 +0800402 // Inform the diagnostic client we are processing a source file
Stephen Hinescc0efad2010-10-04 16:13:02 -0700403 mDiagClient->BeginSourceFile(LangOpts, mPP.get());
404
Zonr Change8c263a2010-10-12 00:35:29 +0800405 // Go through the source file (no operations necessary)
Stephen Hinescc0efad2010-10-04 16:13:02 -0700406 clang::Token Tok;
407 mPP->EnterMainSourceFile();
408 do {
409 mPP->Lex(Tok);
410 } while (Tok.isNot(clang::tok::eof));
411
412 mPP->EndSourceFile();
413
Zonr Change8c263a2010-10-12 00:35:29 +0800414 // Declare success if no error
Loganbe274822011-02-16 22:02:54 +0800415 if (!mDiagnostics->hasErrorOccurred())
Zonr Change8c263a2010-10-12 00:35:29 +0800416 mDOS->keep();
417
418 // Clean up after compilation
Stephen Hinescc0efad2010-10-04 16:13:02 -0700419 mPP.reset();
Zonr Change8c263a2010-10-12 00:35:29 +0800420 mDOS.reset();
Stephen Hinescc0efad2010-10-04 16:13:02 -0700421
Loganbe274822011-02-16 22:02:54 +0800422 return mDiagnostics->hasErrorOccurred() ? 1 : 0;
Stephen Hinescc0efad2010-10-04 16:13:02 -0700423}
424
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700425int Slang::compile() {
Loganbe274822011-02-16 22:02:54 +0800426 if (mDiagnostics->hasErrorOccurred())
427 return 1;
Stephen Hinesf7de8522010-10-06 11:46:18 -0700428 if (mOS.get() == NULL)
429 return 1;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700430
431 // Here is per-compilation needed initialization
432 createPreprocessor();
433 createASTContext();
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800434
Shih-wei Liaodf5bcce2011-02-28 18:39:23 -0800435 mBackend.reset(createBackend(CodeGenOpts, &mOS->os(), mOT));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700436
437 // Inform the diagnostic client we are processing a source file
438 mDiagClient->BeginSourceFile(LangOpts, mPP.get());
439
440 // The core of the slang compiler
441 ParseAST(*mPP, mBackend.get(), *mASTContext);
442
Zonr Change8c263a2010-10-12 00:35:29 +0800443 // Inform the diagnostic client we are done with previous source file
444 mDiagClient->EndSourceFile();
445
446 // Declare success if no error
Loganbe274822011-02-16 22:02:54 +0800447 if (!mDiagnostics->hasErrorOccurred())
Zonr Change8c263a2010-10-12 00:35:29 +0800448 mOS->keep();
449
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800450 // The compilation ended, clear
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700451 mBackend.reset();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700452 mASTContext.reset();
453 mPP.reset();
Zonr Change8c263a2010-10-12 00:35:29 +0800454 mOS.reset();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700455
Loganbe274822011-02-16 22:02:54 +0800456 return mDiagnostics->hasErrorOccurred() ? 1 : 0;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700457}
458
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800459void Slang::reset() {
Stephen Hinesc632be22011-09-23 15:53:16 -0700460 llvm::errs() << mDiagClient->str();
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800461 mDiagnostics->Reset();
462 mDiagClient->reset();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700463 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700464}
465
466Slang::~Slang() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700467 llvm::llvm_shutdown();
468 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700469}
Stephen Hinese639eb52010-11-08 19:27:20 -0800470
471} // namespace slang