slang.cpp revision f83d3c396d5d7eacd97cf0a5d3b6a01d75535b67
1113e0824d6bddf4376240681f9cf6a2deded9498John Reck#include "slang.hpp"
2113e0824d6bddf4376240681f9cf6a2deded9498John Reck
3113e0824d6bddf4376240681f9cf6a2deded9498John Reck#include <stdlib.h>                     /* for getenv */
4113e0824d6bddf4376240681f9cf6a2deded9498John Reck
5113e0824d6bddf4376240681f9cf6a2deded9498John Reck#include "libslang.h"
6113e0824d6bddf4376240681f9cf6a2deded9498John Reck
7113e0824d6bddf4376240681f9cf6a2deded9498John Reck#include "llvm/ADT/Twine.h"     /* for class llvm::Twine */
8113e0824d6bddf4376240681f9cf6a2deded9498John Reck
9113e0824d6bddf4376240681f9cf6a2deded9498John Reck#include "llvm/Target/TargetSelect.h"       /* for function LLVMInitialize[ARM|X86][TargetInfo|Target|AsmPrinter]() */
10113e0824d6bddf4376240681f9cf6a2deded9498John Reck
11113e0824d6bddf4376240681f9cf6a2deded9498John Reck#include "llvm/Support/MemoryBuffer.h"      /* for class llvm::MemoryBuffer */
12113e0824d6bddf4376240681f9cf6a2deded9498John Reck#include "llvm/Support/ErrorHandling.h"     /* for function llvm::install_fatal_error_handler() */
13113e0824d6bddf4376240681f9cf6a2deded9498John Reck#include "llvm/Support/ManagedStatic.h"     /* for class llvm::llvm_shutdown */
14113e0824d6bddf4376240681f9cf6a2deded9498John Reck
15113e0824d6bddf4376240681f9cf6a2deded9498John Reck#include "clang/Basic/TargetInfo.h"     /* for class clang::TargetInfo */
16113e0824d6bddf4376240681f9cf6a2deded9498John Reck#include "clang/Basic/LangOptions.h"    /* for class clang::LangOptions */
17113e0824d6bddf4376240681f9cf6a2deded9498John Reck#include "clang/Basic/TargetOptions.h"  /* for class clang::TargetOptions */
18113e0824d6bddf4376240681f9cf6a2deded9498John Reck
19113e0824d6bddf4376240681f9cf6a2deded9498John Reck#include "clang/Frontend/FrontendDiagnostic.h"      /* for clang::diag::* */
20113e0824d6bddf4376240681f9cf6a2deded9498John Reck
21113e0824d6bddf4376240681f9cf6a2deded9498John Reck#include "clang/Sema/ParseAST.h"        /* for function clang::ParseAST() */
22113e0824d6bddf4376240681f9cf6a2deded9498John Reck
23113e0824d6bddf4376240681f9cf6a2deded9498John Reck#if defined(__arm__)
24113e0824d6bddf4376240681f9cf6a2deded9498John Reck#   define DEFAULT_TARGET_TRIPLE_STRING "armv7-none-linux-gnueabi"
25113e0824d6bddf4376240681f9cf6a2deded9498John Reck#elif defined(__x86_64__)
26113e0824d6bddf4376240681f9cf6a2deded9498John Reck#   define DEFAULT_TARGET_TRIPLE_STRING "x86_64-unknown-linux"
27113e0824d6bddf4376240681f9cf6a2deded9498John Reck#else
28113e0824d6bddf4376240681f9cf6a2deded9498John Reck#   define DEFAULT_TARGET_TRIPLE_STRING "i686-unknown-linux"    // let's use x86 as default target
29113e0824d6bddf4376240681f9cf6a2deded9498John Reck#endif
3068bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
31113e0824d6bddf4376240681f9cf6a2deded9498John Recknamespace slang {
32113e0824d6bddf4376240681f9cf6a2deded9498John Reck
33b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikbool Slang::GlobalInitialized = false;
34113e0824d6bddf4376240681f9cf6a2deded9498John Reck
35113e0824d6bddf4376240681f9cf6a2deded9498John Reck/* Language option (define the language feature for compiler such as C99) */
36272a685f17cc4828257e521a6f62b7b17870f75eJohn ReckLangOptions Slang::LangOpts;
37272a685f17cc4828257e521a6f62b7b17870f75eJohn Reck
38113e0824d6bddf4376240681f9cf6a2deded9498John Reck/* Code generation option for the compiler */
39113e0824d6bddf4376240681f9cf6a2deded9498John ReckCodeGenOptions Slang::CodeGenOpts;
40113e0824d6bddf4376240681f9cf6a2deded9498John Reck
41113e0824d6bddf4376240681f9cf6a2deded9498John Reckconst std::string Slang::TargetDescription = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-n32";
42113e0824d6bddf4376240681f9cf6a2deded9498John Reck
43113e0824d6bddf4376240681f9cf6a2deded9498John Reck/* The named of metadata node that pragma resides (should be synced with bcc.cpp) */
44113e0824d6bddf4376240681f9cf6a2deded9498John Reckconst llvm::Twine Slang::PragmaMetadataName = "#pragma";
45113e0824d6bddf4376240681f9cf6a2deded9498John Reck
46b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid Slang::GlobalInitialization() {
47db663fe83f976107fd8fd9307d871b37d9e47370Chris Craik    if(!GlobalInitialized) {
480b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        /* We only support x86, x64 and ARM target */
49113e0824d6bddf4376240681f9cf6a2deded9498John Reck
500b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        /* For ARM */
51113e0824d6bddf4376240681f9cf6a2deded9498John Reck        LLVMInitializeARMTargetInfo();
52113e0824d6bddf4376240681f9cf6a2deded9498John Reck        LLVMInitializeARMTarget();
53113e0824d6bddf4376240681f9cf6a2deded9498John Reck        LLVMInitializeARMAsmPrinter();
540b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
550b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        /* For x86 and x64 */
568d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        LLVMInitializeX86TargetInfo();
570b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        LLVMInitializeX86Target();
588d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        LLVMInitializeX86AsmPrinter();
590b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
600b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        /* Please refer to clang/include/clang/Basic/LangOptions.h for setting up the options */
610b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        LangOpts.RTTI = 0;  /* turn off the RTTI information support */
628d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        LangOpts.NeXTRuntime = 0;   /* turn off the NeXT runtime uses */
630b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        LangOpts.Bool = 1;  /* turn on 'bool', 'true', 'false' keywords. */
640b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
65113e0824d6bddf4376240681f9cf6a2deded9498John Reck        CodeGenOpts.OptimizationLevel = 3;  /* -O3 */
668d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik
67113e0824d6bddf4376240681f9cf6a2deded9498John Reck        GlobalInitialized = true;
68113e0824d6bddf4376240681f9cf6a2deded9498John Reck    }
69113e0824d6bddf4376240681f9cf6a2deded9498John Reck
702dc236b2bae13b9a0ed9b3f7320502aecd7983b3Tom Hudson    return;
71113e0824d6bddf4376240681f9cf6a2deded9498John Reck}
72e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck
73e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reckvoid Slang::LLVMErrorHandler(void *UserData, const std::string &Message) {
74e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    Diagnostic* Diags = static_cast<Diagnostic*>(UserData);
75e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    Diags->Report(clang::diag::err_fe_error_backend) << Message;
76113e0824d6bddf4376240681f9cf6a2deded9498John Reck    exit(1);
77113e0824d6bddf4376240681f9cf6a2deded9498John Reck}
78113e0824d6bddf4376240681f9cf6a2deded9498John Reck
79113e0824d6bddf4376240681f9cf6a2deded9498John Reckvoid Slang::createTarget(const char* Triple, const char* CPU, const char** Features) {
80003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    if(Triple != NULL)
81113e0824d6bddf4376240681f9cf6a2deded9498John Reck        mTargetOpts.Triple = Triple;
82113e0824d6bddf4376240681f9cf6a2deded9498John Reck    else
83113e0824d6bddf4376240681f9cf6a2deded9498John Reck        mTargetOpts.Triple = DEFAULT_TARGET_TRIPLE_STRING;
84003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik
85003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    if(CPU != NULL)
86113e0824d6bddf4376240681f9cf6a2deded9498John Reck        mTargetOpts.CPU = CPU;
87113e0824d6bddf4376240681f9cf6a2deded9498John Reck
88087bc0c14bdccf7c258dce0cdef46a69a839b427John Reck    mTarget.reset(TargetInfo::CreateTargetInfo(*mDiagnostics, mTargetOpts));
89b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
908d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    if(Features != NULL)
91113e0824d6bddf4376240681f9cf6a2deded9498John Reck        for(int i=0;Features[i]!=NULL;i++)
92ff941dcd815021bb20d6504eb486acb1e50592c3John Reck            mTargetOpts.Features.push_back(Features[i]);
93ff941dcd815021bb20d6504eb486acb1e50592c3John Reck
94ff941dcd815021bb20d6504eb486acb1e50592c3John Reck    return;
95ff941dcd815021bb20d6504eb486acb1e50592c3John Reck}
96ff941dcd815021bb20d6504eb486acb1e50592c3John Reck
97ff941dcd815021bb20d6504eb486acb1e50592c3John Reckvoid Slang::createPreprocessor() {
98ff941dcd815021bb20d6504eb486acb1e50592c3John Reck  HeaderSearch* HS = new HeaderSearch(*mFileMgr); /* Default only search header file in current dir */
99ff941dcd815021bb20d6504eb486acb1e50592c3John Reck
100ff941dcd815021bb20d6504eb486acb1e50592c3John Reck  mPP.reset(new Preprocessor( *mDiagnostics,
101ff941dcd815021bb20d6504eb486acb1e50592c3John Reck                              LangOpts,
102ff941dcd815021bb20d6504eb486acb1e50592c3John Reck                              *mTarget,
103ff941dcd815021bb20d6504eb486acb1e50592c3John Reck                              *mSourceMgr,
104ff941dcd815021bb20d6504eb486acb1e50592c3John Reck                              *HS,
105ff941dcd815021bb20d6504eb486acb1e50592c3John Reck                              NULL,
106a7c2ea20c43ab797bef5801530687e22e83def8fJohn Reck                              true /* OwnsHeaderSearch */));
107ff941dcd815021bb20d6504eb486acb1e50592c3John Reck  /* Initialize the prepocessor */
108ff941dcd815021bb20d6504eb486acb1e50592c3John Reck  mPragmas.clear();
109113e0824d6bddf4376240681f9cf6a2deded9498John Reck  mPP->AddPragmaHandler(NULL, new PragmaRecorder(mPragmas));
110e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
111113e0824d6bddf4376240681f9cf6a2deded9498John Reck  std::string inclFiles("#include \"rs_types.rsh\"");
112113e0824d6bddf4376240681f9cf6a2deded9498John Reck  mPP->setPredefines(inclFiles + "\n" + "#include \"rs_math.rsh\"" + "\n");
113113e0824d6bddf4376240681f9cf6a2deded9498John Reck
114113e0824d6bddf4376240681f9cf6a2deded9498John Reck  /* Like ApplyHeaderSearchOptions in InitHeaderSearch.cpp */
115113e0824d6bddf4376240681f9cf6a2deded9498John Reck  const char *inclDir = getenv("ANDROID_BUILD_TOP");
116113e0824d6bddf4376240681f9cf6a2deded9498John Reck  std::vector<DirectoryLookup> SearchList;
117443a714fa7c0dd07fee3527cc5bc3d3ca1fb7d44John Reck  if (inclDir) {
118113e0824d6bddf4376240681f9cf6a2deded9498John Reck    char *dirPath = new char[strlen(inclDir) + 33];
119003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    strcpy(dirPath, inclDir);
120113e0824d6bddf4376240681f9cf6a2deded9498John Reck    strcpy(dirPath + strlen(inclDir), "/frameworks/base/libs/rs/scriptc");
121113e0824d6bddf4376240681f9cf6a2deded9498John Reck
122b265e2ca50b6ceb2fd2987ef1f7d063b1bde19aeChris Craik    if (const DirectoryEntry *DE = mFileMgr->getDirectory(dirPath, dirPath + strlen(dirPath))) {
12380d4902196899d1325cd9f52c06ae0174cf9bd4cChris Craik      SearchList.push_back(DirectoryLookup(DE, SrcMgr::C_System, false, false));
12480d4902196899d1325cd9f52c06ae0174cf9bd4cChris Craik    }
125113e0824d6bddf4376240681f9cf6a2deded9498John Reck  }
126113e0824d6bddf4376240681f9cf6a2deded9498John Reck
127fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck  int siz = 256;
128e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck  char *currDir = new char[siz];
129113e0824d6bddf4376240681f9cf6a2deded9498John Reck  while (!getcwd(currDir, siz)) {
130113e0824d6bddf4376240681f9cf6a2deded9498John Reck    siz *= 2;
131003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik  }
132113e0824d6bddf4376240681f9cf6a2deded9498John Reck
133113e0824d6bddf4376240681f9cf6a2deded9498John Reck  if (siz - strlen(currDir) >= 33) {
134a447d29c65fb811cd184775a3476101a1cede929John Reck    strcpy(currDir + strlen(currDir), "/frameworks/base/libs/rs/scriptc");
135003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik  } else {
136a447d29c65fb811cd184775a3476101a1cede929John Reck    char *tmp = new char[strlen(currDir) + 33];
137a447d29c65fb811cd184775a3476101a1cede929John Reck    strcpy(tmp, currDir);
138defb7f37fe67ef2389666f7adc5da1260df87017Chris Craik    strcpy(tmp + strlen(currDir), "/frameworks/base/libs/rs/scriptc");
139defb7f37fe67ef2389666f7adc5da1260df87017Chris Craik    currDir = tmp;
140defb7f37fe67ef2389666f7adc5da1260df87017Chris Craik  }
141defb7f37fe67ef2389666f7adc5da1260df87017Chris Craik
142113e0824d6bddf4376240681f9cf6a2deded9498John Reck  if (const DirectoryEntry *DE = mFileMgr->getDirectory(currDir, currDir + strlen(currDir))) {
143113e0824d6bddf4376240681f9cf6a2deded9498John Reck    SearchList.push_back(DirectoryLookup(DE, SrcMgr::C_System, false, false));
144113e0824d6bddf4376240681f9cf6a2deded9498John Reck  }
145113e0824d6bddf4376240681f9cf6a2deded9498John Reck
146113e0824d6bddf4376240681f9cf6a2deded9498John Reck  HS->SetSearchPaths(SearchList, 1, false);
147113e0824d6bddf4376240681f9cf6a2deded9498John Reck
148113e0824d6bddf4376240681f9cf6a2deded9498John Reck  return;
149113e0824d6bddf4376240681f9cf6a2deded9498John Reck}
150113e0824d6bddf4376240681f9cf6a2deded9498John Reck
151113e0824d6bddf4376240681f9cf6a2deded9498John ReckSlang::Slang(const char* Triple, const char* CPU, const char** Features) :
152113e0824d6bddf4376240681f9cf6a2deded9498John Reck    mOutputType(SlangCompilerOutput_Default),
153ff941dcd815021bb20d6504eb486acb1e50592c3John Reck    mAllowRSPrefix(false)
154ff941dcd815021bb20d6504eb486acb1e50592c3John Reck{
155ff941dcd815021bb20d6504eb486acb1e50592c3John Reck    GlobalInitialization();
156ff941dcd815021bb20d6504eb486acb1e50592c3John Reck
157ff941dcd815021bb20d6504eb486acb1e50592c3John Reck    createDiagnostic();
158ff941dcd815021bb20d6504eb486acb1e50592c3John Reck    llvm::install_fatal_error_handler(LLVMErrorHandler, mDiagnostics.get());
159ff941dcd815021bb20d6504eb486acb1e50592c3John Reck
160ff941dcd815021bb20d6504eb486acb1e50592c3John Reck    createTarget(Triple, CPU, Features);
161e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck    createFileManager();
162113e0824d6bddf4376240681f9cf6a2deded9498John Reck    createSourceManager();
163113e0824d6bddf4376240681f9cf6a2deded9498John Reck
164113e0824d6bddf4376240681f9cf6a2deded9498John Reck    return;
16552244fff29042926e21fa897ef5ab11148e35299John Reck}
16652244fff29042926e21fa897ef5ab11148e35299John Reck
16752244fff29042926e21fa897ef5ab11148e35299John Reckbool Slang::setInputSource(llvm::StringRef inputFile, const char* text, size_t textLength) {
16852244fff29042926e21fa897ef5ab11148e35299John Reck    mInputFileName = inputFile.str();
169d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
170d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    /* Reset the ID tables if we are reusing the SourceManager */
171d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    mSourceMgr->clearIDTables();
172d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
173d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    /* Load the source */
174d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    llvm::MemoryBuffer *SB = llvm::MemoryBuffer::getMemBuffer(text, text + textLength);
175d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    mSourceMgr->createMainFileIDForMemBuffer(SB);
176d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
17776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    if(mSourceMgr->getMainFileID().isInvalid()) {
178113e0824d6bddf4376240681f9cf6a2deded9498John Reck        mDiagnostics->Report(clang::diag::err_fe_error_reading) << inputFile;
179113e0824d6bddf4376240681f9cf6a2deded9498John Reck        return false;
180113e0824d6bddf4376240681f9cf6a2deded9498John Reck    }
18176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik
182113e0824d6bddf4376240681f9cf6a2deded9498John Reck    return true;
183113e0824d6bddf4376240681f9cf6a2deded9498John Reck}
184113e0824d6bddf4376240681f9cf6a2deded9498John Reck
185e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reckbool Slang::setInputSource(llvm::StringRef inputFile) {
186dcba6725e8b9d3eba9ad7a01258d6aa974feafbaJohn Reck    mInputFileName = inputFile.str();
187e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
188e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    mSourceMgr->clearIDTables();
18968bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
190668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck    const FileEntry* File = mFileMgr->getFile(inputFile);
191119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    if(File)
192119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck        mSourceMgr->createMainFileID(File, SourceLocation());
19369e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik
19469e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik    if(mSourceMgr->getMainFileID().isInvalid()) {
195b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        mDiagnostics->Report(clang::diag::err_fe_error_reading) << inputFile;
196b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return false;
197003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    }
198b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
199b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return true;
200b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
201b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
202b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid Slang::setOutputType(SlangCompilerOutputTy outputType) {
203b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mOutputType = outputType;
2040b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    if( mOutputType != SlangCompilerOutput_Assembly &&
2050b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        mOutputType != SlangCompilerOutput_LL &&
206b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        mOutputType != SlangCompilerOutput_Bitcode &&
2070b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        mOutputType != SlangCompilerOutput_Nothing &&
2080b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        mOutputType != SlangCompilerOutput_Obj)
2090b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        mOutputType = SlangCompilerOutput_Default;
2100b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    return;
211b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
212113e0824d6bddf4376240681f9cf6a2deded9498John Reck
213a7090e0cfd7c719a6d4c03aae34f5db98754cbddChris Craikstatic void _mkdir_given_a_file(const char *file) {
214113e0824d6bddf4376240681f9cf6a2deded9498John Reck    char buf[256];
215272a685f17cc4828257e521a6f62b7b17870f75eJohn Reck    char *tmp, *p = NULL;
216113e0824d6bddf4376240681f9cf6a2deded9498John Reck    size_t len = strlen(file);
217113e0824d6bddf4376240681f9cf6a2deded9498John Reck
218113e0824d6bddf4376240681f9cf6a2deded9498John Reck    if (len + 1 <= sizeof(buf))
219113e0824d6bddf4376240681f9cf6a2deded9498John Reck        tmp = buf;
220113e0824d6bddf4376240681f9cf6a2deded9498John Reck    else
221113e0824d6bddf4376240681f9cf6a2deded9498John Reck        tmp = new char [len + 1];
222b9ce116dac378b4cf4490f265dcbd5704a1dd43cChris Craik
223b9ce116dac378b4cf4490f265dcbd5704a1dd43cChris Craik    strcpy(tmp, file);
224b9ce116dac378b4cf4490f265dcbd5704a1dd43cChris Craik
225113e0824d6bddf4376240681f9cf6a2deded9498John Reck    if (tmp[len - 1] == '/')
226113e0824d6bddf4376240681f9cf6a2deded9498John Reck        tmp[len - 1] = 0;
2278d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik
2288d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    for (p = tmp + 1; *p; p++) {
229113e0824d6bddf4376240681f9cf6a2deded9498John Reck        if (*p == '/') {
230113e0824d6bddf4376240681f9cf6a2deded9498John Reck            *p = 0;
231113e0824d6bddf4376240681f9cf6a2deded9498John Reck            mkdir(tmp, S_IRWXU);
232b265e2ca50b6ceb2fd2987ef1f7d063b1bde19aeChris Craik            *p = '/';
233113e0824d6bddf4376240681f9cf6a2deded9498John Reck        }
234003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    }
235272a685f17cc4828257e521a6f62b7b17870f75eJohn Reck
236113e0824d6bddf4376240681f9cf6a2deded9498John Reck    if (tmp != buf)
237b265e2ca50b6ceb2fd2987ef1f7d063b1bde19aeChris Craik        delete[] tmp;
238b265e2ca50b6ceb2fd2987ef1f7d063b1bde19aeChris Craik}
239b265e2ca50b6ceb2fd2987ef1f7d063b1bde19aeChris Craik
240113e0824d6bddf4376240681f9cf6a2deded9498John Reckbool Slang::setOutput(const char* outputFile) {
241c3e75f9d54b3629b3fd27afafa2e07bd07dad9b3Chris Craik    std::string Error;
242272a685f17cc4828257e521a6f62b7b17870f75eJohn Reck
24380d4902196899d1325cd9f52c06ae0174cf9bd4cChris Craik    _mkdir_given_a_file(outputFile);
244113e0824d6bddf4376240681f9cf6a2deded9498John Reck
245113e0824d6bddf4376240681f9cf6a2deded9498John Reck    switch(mOutputType) {
246b265e2ca50b6ceb2fd2987ef1f7d063b1bde19aeChris Craik        case SlangCompilerOutput_Assembly:
247113e0824d6bddf4376240681f9cf6a2deded9498John Reck        case SlangCompilerOutput_LL:
248b265e2ca50b6ceb2fd2987ef1f7d063b1bde19aeChris Craik            mOS.reset( new llvm::raw_fd_ostream(outputFile, Error, 0) );
249b265e2ca50b6ceb2fd2987ef1f7d063b1bde19aeChris Craik        break;
250a7090e0cfd7c719a6d4c03aae34f5db98754cbddChris Craik
251b265e2ca50b6ceb2fd2987ef1f7d063b1bde19aeChris Craik        case SlangCompilerOutput_Nothing:
252113e0824d6bddf4376240681f9cf6a2deded9498John Reck            mOS.reset();
253b265e2ca50b6ceb2fd2987ef1f7d063b1bde19aeChris Craik        break;
254113e0824d6bddf4376240681f9cf6a2deded9498John Reck
255113e0824d6bddf4376240681f9cf6a2deded9498John Reck        case SlangCompilerOutput_Obj:
256113e0824d6bddf4376240681f9cf6a2deded9498John Reck        case SlangCompilerOutput_Bitcode:
257113e0824d6bddf4376240681f9cf6a2deded9498John Reck        default:
258113e0824d6bddf4376240681f9cf6a2deded9498John Reck            mOS.reset( new llvm::raw_fd_ostream(outputFile, Error, llvm::raw_fd_ostream::F_Binary) );
259113e0824d6bddf4376240681f9cf6a2deded9498John Reck        break;
260113e0824d6bddf4376240681f9cf6a2deded9498John Reck    }
261113e0824d6bddf4376240681f9cf6a2deded9498John Reck
262113e0824d6bddf4376240681f9cf6a2deded9498John Reck    if(!Error.empty()) {
263113e0824d6bddf4376240681f9cf6a2deded9498John Reck        mOS.reset();
264113e0824d6bddf4376240681f9cf6a2deded9498John Reck        mDiagnostics->Report(clang::diag::err_fe_error_opening) << outputFile << Error;
265113e0824d6bddf4376240681f9cf6a2deded9498John Reck        return false;
266113e0824d6bddf4376240681f9cf6a2deded9498John Reck    }
267113e0824d6bddf4376240681f9cf6a2deded9498John Reck
268113e0824d6bddf4376240681f9cf6a2deded9498John Reck    mOutputFileName = outputFile;
269b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
270b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return true;
271b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
272b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
273a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craikint Slang::compile() {
27425fbb3fa1138675379102a44405852555cefccbdJohn Reck    if((mDiagnostics->getNumErrors() > 0) || (mOS.get() == NULL))
27525fbb3fa1138675379102a44405852555cefccbdJohn Reck        return mDiagnostics->getNumErrors();
276003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik
2770b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    /* Here is per-compilation needed initialization */
27825fbb3fa1138675379102a44405852555cefccbdJohn Reck    createPreprocessor();
2790b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    createASTContext();
280a7c2ea20c43ab797bef5801530687e22e83def8fJohn Reck    createRSContext();
28125fbb3fa1138675379102a44405852555cefccbdJohn Reck    //createBackend();
282003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    createRSBackend();
2830a97330b98dd633b58dcfff405d94476c89e867dJohn Reck
284dcba6725e8b9d3eba9ad7a01258d6aa974feafbaJohn Reck    /* Inform the diagnostic client we are processing a source file */
285dcba6725e8b9d3eba9ad7a01258d6aa974feafbaJohn Reck    mDiagClient->BeginSourceFile(LangOpts, mPP.get());
286dcba6725e8b9d3eba9ad7a01258d6aa974feafbaJohn Reck
2878de65a8e05285df52a1e6f0c1d5616dd233298a7John Reck    /* The core of the slang compiler */
288113e0824d6bddf4376240681f9cf6a2deded9498John Reck    ParseAST(*mPP, mBackend.get(), *mASTContext);
289113e0824d6bddf4376240681f9cf6a2deded9498John Reck
290ff941dcd815021bb20d6504eb486acb1e50592c3John Reck    /* The compilation ended, clear up */
291113e0824d6bddf4376240681f9cf6a2deded9498John Reck    mBackend.reset();
292d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    // Can't reset yet because the reflection later on still needs mRSContext
293d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    //    mRSContext.reset();
294003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    mASTContext.reset();
295003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    mPP.reset();
296003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik
297003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    /* Inform the diagnostic client we are done with previous source file */
298113e0824d6bddf4376240681f9cf6a2deded9498John Reck    mDiagClient->EndSourceFile();
29968bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck
30068bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    return mDiagnostics->getNumErrors();
301e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck}
30225fbb3fa1138675379102a44405852555cefccbdJohn Reck
30325fbb3fa1138675379102a44405852555cefccbdJohn Reckbool Slang::reflectToJava(const char* outputPackageName) {
3040b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    if(mRSContext.get())
30525fbb3fa1138675379102a44405852555cefccbdJohn Reck        return mRSContext->reflectToJava(outputPackageName, mInputFileName, mOutputFileName);
306113e0824d6bddf4376240681f9cf6a2deded9498John Reck    else
307113e0824d6bddf4376240681f9cf6a2deded9498John Reck        return false;
308113e0824d6bddf4376240681f9cf6a2deded9498John Reck}
309113e0824d6bddf4376240681f9cf6a2deded9498John Reck
310113e0824d6bddf4376240681f9cf6a2deded9498John Reckbool Slang::reflectToJavaPath(const char* outputPathName) {
3118d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    if(mRSContext.get())
312dcba6725e8b9d3eba9ad7a01258d6aa974feafbaJohn Reck        return mRSContext->reflectToJavaPath(outputPathName);
313dcba6725e8b9d3eba9ad7a01258d6aa974feafbaJohn Reck    else
314dcba6725e8b9d3eba9ad7a01258d6aa974feafbaJohn Reck        return false;
315dcba6725e8b9d3eba9ad7a01258d6aa974feafbaJohn Reck}
316dcba6725e8b9d3eba9ad7a01258d6aa974feafbaJohn Reck
317dcba6725e8b9d3eba9ad7a01258d6aa974feafbaJohn Reckvoid Slang::getPragmas(size_t* actualStringCount, size_t maxStringCount, char** strings) {
318003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    int stringCount = mPragmas.size() * 2;
319dcba6725e8b9d3eba9ad7a01258d6aa974feafbaJohn Reck
320113e0824d6bddf4376240681f9cf6a2deded9498John Reck    if(actualStringCount)
321113e0824d6bddf4376240681f9cf6a2deded9498John Reck        *actualStringCount = stringCount;
322113e0824d6bddf4376240681f9cf6a2deded9498John Reck    if(stringCount > maxStringCount)
323113e0824d6bddf4376240681f9cf6a2deded9498John Reck        stringCount = maxStringCount;
324113e0824d6bddf4376240681f9cf6a2deded9498John Reck    if(strings)
325113e0824d6bddf4376240681f9cf6a2deded9498John Reck        for(PragmaList::const_iterator it = mPragmas.begin();
326            stringCount > 0;
327            stringCount-=2, it++)
328        {
329            *strings++ = const_cast<char*>(it->first.c_str());
330            *strings++ = const_cast<char*>(it->second.c_str());
331        }
332
333    return;
334}
335
336Slang::~Slang() {
337    llvm::llvm_shutdown();
338    return;
339}
340
341}   /* namespace slang */
342