blob: 3b6ccf9a95df3ac50510aa801b59f5c3b21e8cf1 [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 Hines23c43582013-01-09 20:02:04 -080028#include "clang/Basic/DiagnosticOptions.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080029#include "clang/Basic/FileManager.h"
Shih-wei Liaodf5bcce2011-02-28 18:39:23 -080030#include "clang/Basic/FileSystemOptions.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080031#include "clang/Basic/LangOptions.h"
32#include "clang/Basic/SourceManager.h"
33#include "clang/Basic/TargetInfo.h"
34#include "clang/Basic/TargetOptions.h"
35
36#include "clang/Frontend/CodeGenOptions.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080037#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"
Stephen Hines23c43582013-01-09 20:02:04 -080043#include "clang/Lex/PreprocessorOptions.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080044#include "clang/Lex/HeaderSearch.h"
Stephen Hines23c43582013-01-09 20:02:04 -080045#include "clang/Lex/HeaderSearchOptions.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080046
47#include "clang/Parse/ParseAST.h"
48
Loganbe274822011-02-16 22:02:54 +080049#include "llvm/ADT/IntrusiveRefCntPtr.h"
50
Stephen Hinese639eb52010-11-08 19:27:20 -080051#include "llvm/Bitcode/ReaderWriter.h"
52
53// More force linking
54#include "llvm/Linker.h"
55
Zonr Chang08df36e2010-10-07 18:50:42 +080056// Force linking all passes/vmcore stuffs to libslang.so
Stephen Hines0da7f6c2013-03-05 15:19:02 -080057#include "llvm/LinkAllIR.h"
Zonr Chang08df36e2010-10-07 18:50:42 +080058#include "llvm/LinkAllPasses.h"
Zonr Chang08df36e2010-10-07 18:50:42 +080059
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080060#include "llvm/Support/raw_ostream.h"
zonr6315f762010-10-05 15:35:14 +080061#include "llvm/Support/MemoryBuffer.h"
62#include "llvm/Support/ErrorHandling.h"
63#include "llvm/Support/ManagedStatic.h"
Loganbe274822011-02-16 22:02:54 +080064#include "llvm/Support/Path.h"
Logan Chien9207a2e2011-10-21 15:39:28 +080065#include "llvm/Support/TargetSelect.h"
66#include "llvm/Support/ToolOutputFile.h"
Stephen Hinescc0efad2010-10-04 16:13:02 -070067
Stephen Hines6e6578a2011-02-07 18:05:48 -080068#include "slang_assert.h"
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080069#include "slang_backend.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080070#include "slang_utils.h"
Shih-wei Liaob81c6a42010-10-10 14:15:00 -070071
Zonr Chang08df36e2010-10-07 18:50:42 +080072namespace {
Zonr Chang08df36e2010-10-07 18:50:42 +080073
Stephen Hinese639eb52010-11-08 19:27:20 -080074struct ForceSlangLinking {
75 ForceSlangLinking() {
76 // We must reference the functions in such a way that compilers will not
77 // delete it all as dead code, even with whole program optimization,
78 // yet is effectively a NO-OP. As the compiler isn't smart enough
79 // to know that getenv() never returns -1, this will do the job.
80 if (std::getenv("bar") != reinterpret_cast<char*>(-1))
81 return;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -070082
Stephen Hinese639eb52010-11-08 19:27:20 -080083 // llvm-rs-link needs following functions existing in libslang.
84 llvm::ParseBitcodeFile(NULL, llvm::getGlobalContext(), NULL);
Logan Chien9207a2e2011-10-21 15:39:28 +080085 llvm::Linker::LinkModules(NULL, NULL, 0, NULL);
Zonr Chang08df36e2010-10-07 18:50:42 +080086
Stephen Hinese639eb52010-11-08 19:27:20 -080087 // llvm-rs-cc need this.
88 new clang::TextDiagnosticPrinter(llvm::errs(),
Stephen Hines23c43582013-01-09 20:02:04 -080089 new clang::DiagnosticOptions());
Stephen Hinese639eb52010-11-08 19:27:20 -080090 }
91} ForceSlangLinking;
92
93} // namespace
94
95namespace slang {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070096
Shih-wei Liao462aefd2010-06-04 15:32:04 -070097#if defined(__arm__)
98# define DEFAULT_TARGET_TRIPLE_STRING "armv7-none-linux-gnueabi"
99#elif defined(__x86_64__)
100# define DEFAULT_TARGET_TRIPLE_STRING "x86_64-unknown-linux"
101#else
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700102// let's use x86 as default target
103# define DEFAULT_TARGET_TRIPLE_STRING "i686-unknown-linux"
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700104#endif
105
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700106bool Slang::GlobalInitialized = false;
107
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700108// Language option (define the language feature for compiler such as C99)
109clang::LangOptions Slang::LangOpts;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700110
zonr6315f762010-10-05 15:35:14 +0800111// Code generation option for the compiler
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700112clang::CodeGenOptions Slang::CodeGenOpts;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700113
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700114// The named of metadata node that pragma resides (should be synced with
115// bcc.cpp)
Shih-wei Liaof52a6202010-09-10 17:40:53 -0700116const llvm::StringRef Slang::PragmaMetadataName = "#pragma";
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700117
Logan Chien9207a2e2011-10-21 15:39:28 +0800118static inline llvm::tool_output_file *
119OpenOutputFile(const char *OutputFile,
120 unsigned Flags,
121 std::string* Error,
Stephen Hinese67239d2012-02-24 15:08:36 -0800122 clang::DiagnosticsEngine *DiagEngine) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800123 slangAssert((OutputFile != NULL) && (Error != NULL) &&
124 (DiagEngine != NULL) && "Invalid parameter!");
Zonr Change8c263a2010-10-12 00:35:29 +0800125
Logan Chien6f4e0a92011-03-10 01:10:25 +0800126 if (SlangUtils::CreateDirectoryWithParents(
127 llvm::sys::path::parent_path(OutputFile), Error)) {
Zonr Change8c263a2010-10-12 00:35:29 +0800128 llvm::tool_output_file *F =
129 new llvm::tool_output_file(OutputFile, *Error, Flags);
130 if (F != NULL)
131 return F;
132 }
133
134 // Report error here.
Logan Chien9207a2e2011-10-21 15:39:28 +0800135 DiagEngine->Report(clang::diag::err_fe_error_opening)
136 << OutputFile << *Error;
Zonr Change8c263a2010-10-12 00:35:29 +0800137
138 return NULL;
139}
140
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700141void Slang::GlobalInitialization() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700142 if (!GlobalInitialized) {
143 // We only support x86, x64 and ARM target
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700144
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700145 // For ARM
146 LLVMInitializeARMTargetInfo();
147 LLVMInitializeARMTarget();
148 LLVMInitializeARMAsmPrinter();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700149
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700150 // For x86 and x64
151 LLVMInitializeX86TargetInfo();
152 LLVMInitializeX86Target();
153 LLVMInitializeX86AsmPrinter();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700154
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800155 // Please refer to include/clang/Basic/LangOptions.h to setup
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700156 // the options.
157 LangOpts.RTTI = 0; // Turn off the RTTI information support
Shih-wei Liao245eba12011-01-19 02:14:07 -0800158 LangOpts.C99 = 1;
Stephen Hines52d132c2012-08-01 18:48:06 -0700159 LangOpts.Renderscript = 1;
Stephen Hinesf64e7662013-05-14 13:54:06 -0700160 LangOpts.LaxVectorConversions = 0; // Do not bitcast vectors!
Stephen Hines194d4032012-02-27 18:01:09 -0800161 LangOpts.CharIsSigned = 1; // Signed char is our default.
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700162
mkopec1c460b372012-01-09 11:21:50 -0500163 CodeGenOpts.OptimizationLevel = 3;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700164
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700165 GlobalInitialized = true;
166 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700167}
168
Stephen Hines4b3f3ba2013-05-06 16:18:56 -0700169void Slang::LLVMErrorHandler(void *UserData, const std::string &Message,
170 bool GenCrashDialog) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800171 clang::DiagnosticsEngine* DiagEngine =
172 static_cast<clang::DiagnosticsEngine *>(UserData);
173
174 DiagEngine->Report(clang::diag::err_fe_error_backend) << Message;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700175 exit(1);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700176}
177
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700178void Slang::createTarget(const std::string &Triple, const std::string &CPU,
179 const std::vector<std::string> &Features) {
180 if (!Triple.empty())
Stephen Hines23c43582013-01-09 20:02:04 -0800181 mTargetOpts->Triple = Triple;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700182 else
Stephen Hines23c43582013-01-09 20:02:04 -0800183 mTargetOpts->Triple = DEFAULT_TARGET_TRIPLE_STRING;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700184
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700185 if (!CPU.empty())
Stephen Hines23c43582013-01-09 20:02:04 -0800186 mTargetOpts->CPU = CPU;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700187
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700188 if (!Features.empty())
Stephen Hines23c43582013-01-09 20:02:04 -0800189 mTargetOpts->FeaturesAsWritten = Features;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700190
Logan Chien9207a2e2011-10-21 15:39:28 +0800191 mTarget.reset(clang::TargetInfo::CreateTargetInfo(*mDiagEngine,
Stephen Hines23c43582013-01-09 20:02:04 -0800192 mTargetOpts.getPtr()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700193}
194
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800195void Slang::createFileManager() {
Shih-wei Liaodf5bcce2011-02-28 18:39:23 -0800196 mFileSysOpt.reset(new clang::FileSystemOptions());
Loganbe274822011-02-16 22:02:54 +0800197 mFileMgr.reset(new clang::FileManager(*mFileSysOpt));
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800198}
199
200void Slang::createSourceManager() {
Logan Chien9207a2e2011-10-21 15:39:28 +0800201 mSourceMgr.reset(new clang::SourceManager(*mDiagEngine, *mFileMgr));
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800202}
203
Shih-wei Liao68e8e9f2010-07-18 18:46:49 -0700204void Slang::createPreprocessor() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700205 // Default only search header file in current dir
Stephen Hines23c43582013-01-09 20:02:04 -0800206 llvm::IntrusiveRefCntPtr<clang::HeaderSearchOptions> HSOpts =
207 new clang::HeaderSearchOptions();
208 clang::HeaderSearch *HeaderInfo = new clang::HeaderSearch(HSOpts,
209 *mFileMgr,
Stephen Hines0444de02012-03-02 23:19:06 -0800210 *mDiagEngine,
211 LangOpts,
212 mTarget.get());
Shih-wei Liao68e8e9f2010-07-18 18:46:49 -0700213
Stephen Hines23c43582013-01-09 20:02:04 -0800214 llvm::IntrusiveRefCntPtr<clang::PreprocessorOptions> PPOpts =
215 new clang::PreprocessorOptions();
216 mPP.reset(new clang::Preprocessor(PPOpts,
217 *mDiagEngine,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700218 LangOpts,
Logan Chien9207a2e2011-10-21 15:39:28 +0800219 mTarget.get(),
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700220 *mSourceMgr,
Logan Chien9207a2e2011-10-21 15:39:28 +0800221 *HeaderInfo,
222 *this,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700223 NULL,
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800224 /* OwnsHeaderSearch = */true));
Stephen Hines3fd0a942011-01-18 12:27:39 -0800225 // Initialize the preprocessor
Shih-wei Liao68e8e9f2010-07-18 18:46:49 -0700226 mPragmas.clear();
Stephen Hines3fd0a942011-01-18 12:27:39 -0800227 mPP->AddPragmaHandler(new PragmaRecorder(&mPragmas));
Shih-wei Liao68e8e9f2010-07-18 18:46:49 -0700228
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700229 std::vector<clang::DirectoryLookup> SearchList;
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800230 for (unsigned i = 0, e = mIncludePaths.size(); i != e; i++) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700231 if (const clang::DirectoryEntry *DE =
Loganbe274822011-02-16 22:02:54 +0800232 mFileMgr->getDirectory(mIncludePaths[i])) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700233 SearchList.push_back(clang::DirectoryLookup(DE,
234 clang::SrcMgr::C_System,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700235 false));
236 }
Shih-wei Liao90898282010-07-19 18:38:57 -0700237 }
238
Logan Chien9207a2e2011-10-21 15:39:28 +0800239 HeaderInfo->SetSearchPaths(SearchList,
240 /* angledDirIdx = */1,
241 /* systemDixIdx = */1,
242 /* noCurDirSearch = */false);
Shih-wei Liao90898282010-07-19 18:38:57 -0700243
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800244 initPreprocessor();
Shih-wei Liao68e8e9f2010-07-18 18:46:49 -0700245}
246
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800247void Slang::createASTContext() {
248 mASTContext.reset(new clang::ASTContext(LangOpts,
249 *mSourceMgr,
Logan Chien9207a2e2011-10-21 15:39:28 +0800250 mTarget.get(),
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800251 mPP->getIdentifierTable(),
252 mPP->getSelectorTable(),
253 mPP->getBuiltinInfo(),
254 /* size_reserve = */0));
255 initASTContext();
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800256}
257
Logan Chien9207a2e2011-10-21 15:39:28 +0800258clang::ASTConsumer *
259Slang::createBackend(const clang::CodeGenOptions& CodeGenOpts,
260 llvm::raw_ostream *OS, OutputType OT) {
Stephen Hines23c43582013-01-09 20:02:04 -0800261 return new Backend(mDiagEngine, CodeGenOpts, getTargetOptions(),
Logan Chien9207a2e2011-10-21 15:39:28 +0800262 &mPragmas, OS, OT);
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800263}
264
Zonr Chang641558f2010-10-12 21:07:06 +0800265Slang::Slang() : mInitialized(false), mDiagClient(NULL), mOT(OT_Default) {
Stephen Hines23c43582013-01-09 20:02:04 -0800266 mTargetOpts = new clang::TargetOptions();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700267 GlobalInitialization();
Zonr Chang641558f2010-10-12 21:07:06 +0800268}
269
270void Slang::init(const std::string &Triple, const std::string &CPU,
Stephen Hines8f4d9722011-12-05 14:14:42 -0800271 const std::vector<std::string> &Features,
272 clang::DiagnosticsEngine *DiagEngine,
273 DiagnosticBuffer *DiagClient) {
Zonr Chang641558f2010-10-12 21:07:06 +0800274 if (mInitialized)
275 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700276
Stephen Hines8f4d9722011-12-05 14:14:42 -0800277 mDiagEngine = DiagEngine;
278 mDiagClient = DiagClient;
279 mDiag.reset(new clang::Diagnostic(mDiagEngine));
280 initDiagnostic();
281 llvm::install_fatal_error_handler(LLVMErrorHandler, mDiagEngine);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700282
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700283 createTarget(Triple, CPU, Features);
284 createFileManager();
285 createSourceManager();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700286
Zonr Chang641558f2010-10-12 21:07:06 +0800287 mInitialized = true;
Logan Chien9207a2e2011-10-21 15:39:28 +0800288}
Zonr Chang641558f2010-10-12 21:07:06 +0800289
Stephen Hines23c43582013-01-09 20:02:04 -0800290clang::ModuleLoadResult Slang::loadModule(
291 clang::SourceLocation ImportLoc,
292 clang::ModuleIdPath Path,
293 clang::Module::NameVisibilityKind Visibility,
294 bool IsInclusionDirective) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800295 slangAssert(0 && "Not implemented");
Stephen Hines23c43582013-01-09 20:02:04 -0800296 return clang::ModuleLoadResult();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700297}
298
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800299bool Slang::setInputSource(llvm::StringRef InputFile,
300 const char *Text,
301 size_t TextLength) {
302 mInputFileName = InputFile.str();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700303
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700304 // Reset the ID tables if we are reusing the SourceManager
305 mSourceMgr->clearIDTables();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700306
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700307 // Load the source
zonr6315f762010-10-05 15:35:14 +0800308 llvm::MemoryBuffer *SB =
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800309 llvm::MemoryBuffer::getMemBuffer(Text, Text + TextLength);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700310 mSourceMgr->createMainFileIDForMemBuffer(SB);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700311
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700312 if (mSourceMgr->getMainFileID().isInvalid()) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800313 mDiagEngine->Report(clang::diag::err_fe_error_reading) << InputFile;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700314 return false;
315 }
316 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700317}
318
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800319bool Slang::setInputSource(llvm::StringRef InputFile) {
320 mInputFileName = InputFile.str();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700321
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700322 mSourceMgr->clearIDTables();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700323
Loganbe274822011-02-16 22:02:54 +0800324 const clang::FileEntry *File = mFileMgr->getFile(InputFile);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700325 if (File)
326 mSourceMgr->createMainFileID(File);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700327
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700328 if (mSourceMgr->getMainFileID().isInvalid()) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800329 mDiagEngine->Report(clang::diag::err_fe_error_reading) << InputFile;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700330 return false;
331 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700332
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700333 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700334}
335
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800336bool Slang::setOutput(const char *OutputFile) {
Zonr Chang8c6d9b22010-10-07 18:01:19 +0800337 llvm::sys::Path OutputFilePath(OutputFile);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700338 std::string Error;
Zonr Change8c263a2010-10-12 00:35:29 +0800339 llvm::tool_output_file *OS = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700340
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800341 switch (mOT) {
Stephen Hinescc0efad2010-10-04 16:13:02 -0700342 case OT_Dependency:
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800343 case OT_Assembly:
344 case OT_LLVMAssembly: {
Stephen Hines8f4d9722011-12-05 14:14:42 -0800345 OS = OpenOutputFile(OutputFile, 0, &Error, mDiagEngine);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700346 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700347 }
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800348 case OT_Nothing: {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700349 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700350 }
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800351 case OT_Object:
Stephen Hinescc0efad2010-10-04 16:13:02 -0700352 case OT_Bitcode: {
Logan Chien9207a2e2011-10-21 15:39:28 +0800353 OS = OpenOutputFile(OutputFile, llvm::raw_fd_ostream::F_Binary,
Stephen Hines8f4d9722011-12-05 14:14:42 -0800354 &Error, mDiagEngine);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700355 break;
356 }
Zonr Chang8c6d9b22010-10-07 18:01:19 +0800357 default: {
Stephen Hinescc0efad2010-10-04 16:13:02 -0700358 llvm_unreachable("Unknown compiler output type");
Zonr Chang8c6d9b22010-10-07 18:01:19 +0800359 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700360 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700361
Zonr Change8c263a2010-10-12 00:35:29 +0800362 if (!Error.empty())
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700363 return false;
Zonr Change8c263a2010-10-12 00:35:29 +0800364
365 mOS.reset(OS);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700366
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800367 mOutputFileName = OutputFile;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700368
369 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700370}
371
Stephen Hines0b7ef1a2010-10-07 16:36:59 -0700372bool Slang::setDepOutput(const char *OutputFile) {
Zonr Chang8c6d9b22010-10-07 18:01:19 +0800373 llvm::sys::Path OutputFilePath(OutputFile);
Stephen Hines0b7ef1a2010-10-07 16:36:59 -0700374 std::string Error;
Zonr Chang8c6d9b22010-10-07 18:01:19 +0800375
Stephen Hines8f4d9722011-12-05 14:14:42 -0800376 mDOS.reset(OpenOutputFile(OutputFile, 0, &Error, mDiagEngine));
Zonr Change8c263a2010-10-12 00:35:29 +0800377 if (!Error.empty() || (mDOS.get() == NULL))
Stephen Hines0b7ef1a2010-10-07 16:36:59 -0700378 return false;
Stephen Hines0b7ef1a2010-10-07 16:36:59 -0700379
380 mDepOutputFileName = OutputFile;
381
382 return true;
383}
384
Stephen Hinescc0efad2010-10-04 16:13:02 -0700385int Slang::generateDepFile() {
Logan Chien9207a2e2011-10-21 15:39:28 +0800386 if (mDiagEngine->hasErrorOccurred())
Loganbe274822011-02-16 22:02:54 +0800387 return 1;
Stephen Hines0b7ef1a2010-10-07 16:36:59 -0700388 if (mDOS.get() == NULL)
Stephen Hinesf7de8522010-10-06 11:46:18 -0700389 return 1;
Stephen Hinescc0efad2010-10-04 16:13:02 -0700390
Zonr Change8c263a2010-10-12 00:35:29 +0800391 // Initialize options for generating dependency file
Stephen Hinescc0efad2010-10-04 16:13:02 -0700392 clang::DependencyOutputOptions DepOpts;
393 DepOpts.IncludeSystemHeaders = 1;
Stephen Hines0b7ef1a2010-10-07 16:36:59 -0700394 DepOpts.OutputFile = mDepOutputFileName;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700395 DepOpts.Targets = mAdditionalDepTargets;
Stephen Hinescc0efad2010-10-04 16:13:02 -0700396 DepOpts.Targets.push_back(mDepTargetBCFileName);
Stephen Hines4cc67fc2011-01-31 16:48:57 -0800397 for (std::vector<std::string>::const_iterator
398 I = mGeneratedFileNames.begin(), E = mGeneratedFileNames.end();
399 I != E;
400 I++) {
401 DepOpts.Targets.push_back(*I);
402 }
403 mGeneratedFileNames.clear();
Stephen Hinescc0efad2010-10-04 16:13:02 -0700404
Zonr Change8c263a2010-10-12 00:35:29 +0800405 // Per-compilation needed initialization
Stephen Hinescc0efad2010-10-04 16:13:02 -0700406 createPreprocessor();
407 AttachDependencyFileGen(*mPP.get(), DepOpts);
408
Zonr Change8c263a2010-10-12 00:35:29 +0800409 // Inform the diagnostic client we are processing a source file
Stephen Hinescc0efad2010-10-04 16:13:02 -0700410 mDiagClient->BeginSourceFile(LangOpts, mPP.get());
411
Zonr Change8c263a2010-10-12 00:35:29 +0800412 // Go through the source file (no operations necessary)
Stephen Hinescc0efad2010-10-04 16:13:02 -0700413 clang::Token Tok;
414 mPP->EnterMainSourceFile();
415 do {
416 mPP->Lex(Tok);
417 } while (Tok.isNot(clang::tok::eof));
418
419 mPP->EndSourceFile();
420
Zonr Change8c263a2010-10-12 00:35:29 +0800421 // Declare success if no error
Logan Chien9207a2e2011-10-21 15:39:28 +0800422 if (!mDiagEngine->hasErrorOccurred())
Zonr Change8c263a2010-10-12 00:35:29 +0800423 mDOS->keep();
424
425 // Clean up after compilation
Stephen Hinescc0efad2010-10-04 16:13:02 -0700426 mPP.reset();
Zonr Change8c263a2010-10-12 00:35:29 +0800427 mDOS.reset();
Stephen Hinescc0efad2010-10-04 16:13:02 -0700428
Logan Chien9207a2e2011-10-21 15:39:28 +0800429 return mDiagEngine->hasErrorOccurred() ? 1 : 0;
Stephen Hinescc0efad2010-10-04 16:13:02 -0700430}
431
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700432int Slang::compile() {
Logan Chien9207a2e2011-10-21 15:39:28 +0800433 if (mDiagEngine->hasErrorOccurred())
Loganbe274822011-02-16 22:02:54 +0800434 return 1;
Stephen Hinesf7de8522010-10-06 11:46:18 -0700435 if (mOS.get() == NULL)
436 return 1;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700437
438 // Here is per-compilation needed initialization
439 createPreprocessor();
440 createASTContext();
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800441
Shih-wei Liaodf5bcce2011-02-28 18:39:23 -0800442 mBackend.reset(createBackend(CodeGenOpts, &mOS->os(), mOT));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700443
444 // Inform the diagnostic client we are processing a source file
445 mDiagClient->BeginSourceFile(LangOpts, mPP.get());
446
447 // The core of the slang compiler
448 ParseAST(*mPP, mBackend.get(), *mASTContext);
449
Zonr Change8c263a2010-10-12 00:35:29 +0800450 // Inform the diagnostic client we are done with previous source file
451 mDiagClient->EndSourceFile();
452
453 // Declare success if no error
Logan Chien9207a2e2011-10-21 15:39:28 +0800454 if (!mDiagEngine->hasErrorOccurred())
Zonr Change8c263a2010-10-12 00:35:29 +0800455 mOS->keep();
456
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800457 // The compilation ended, clear
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700458 mBackend.reset();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700459 mASTContext.reset();
460 mPP.reset();
Zonr Change8c263a2010-10-12 00:35:29 +0800461 mOS.reset();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700462
Logan Chien9207a2e2011-10-21 15:39:28 +0800463 return mDiagEngine->hasErrorOccurred() ? 1 : 0;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700464}
465
mkopec1c460b372012-01-09 11:21:50 -0500466void Slang::setDebugMetadataEmission(bool EmitDebug) {
Shih-wei Liao43730fe2012-08-02 23:06:18 -0700467 if (EmitDebug)
Stephen Hines23c43582013-01-09 20:02:04 -0800468 CodeGenOpts.setDebugInfo(clang::CodeGenOptions::FullDebugInfo);
Shih-wei Liao43730fe2012-08-02 23:06:18 -0700469 else
Stephen Hines23c43582013-01-09 20:02:04 -0800470 CodeGenOpts.setDebugInfo(clang::CodeGenOptions::NoDebugInfo);
mkopec1c460b372012-01-09 11:21:50 -0500471}
472
473void Slang::setOptimizationLevel(llvm::CodeGenOpt::Level OptimizationLevel) {
474 CodeGenOpts.OptimizationLevel = OptimizationLevel;
475}
476
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800477void Slang::reset() {
Stephen Hinesc632be22011-09-23 15:53:16 -0700478 llvm::errs() << mDiagClient->str();
Logan Chien9207a2e2011-10-21 15:39:28 +0800479 mDiagEngine->Reset();
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800480 mDiagClient->reset();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700481}
482
483Slang::~Slang() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700484 llvm::llvm_shutdown();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700485}
Stephen Hinese639eb52010-11-08 19:27:20 -0800486
487} // namespace slang