blob: 7883ebbf63ff8f0611f7f09f314b84ddafd983eb [file] [log] [blame]
#ifndef _SLANG_COMPILER_SLANG_HPP
# define _SLANG_COMPILER_SLANG_HPP
#include "slang_backend.hpp"
#include "slang_rs_context.hpp"
#include "slang_rs_backend.hpp"
#include "slang_pragma_recorder.hpp"
#include "slang_diagnostic_buffer.hpp"
#include <cstdio>
#include <string>
#include "llvm/Support/raw_ostream.h" /* for class llvm::raw_ostream */
#include "llvm/ADT/OwningPtr.h" /* for class llvm::OwningPtr */
#include "llvm/ADT/StringRef.h" /* for class llvm::StringRef */
#include "clang/AST/ASTConsumer.h" /* for class clang::ASTConsumer */
#include "clang/AST/ASTContext.h" /* for class clang::ASTContext */
#include "clang/Lex/Preprocessor.h" /* for class clang::Preprocessor */
#include "clang/Lex/HeaderSearch.h" /* for class clang::HeaderSearch */
#include "clang/Basic/Diagnostic.h" /* for class clang::Diagnostic, class clang::DiagnosticClient, class clang::DiagnosticInfo */
#include "clang/Basic/FileManager.h" /* for class clang::FileManager and class clang::FileEntry */
#include "clang/Basic/TargetOptions.h" /* for class clang::TargetOptions */
namespace llvm {
class Twine;
class TargetInfo;
} /* namespace llvm */
namespace clang {
class LangOptions;
class CodeGenOptions;
} /* namespace clang */
namespace slang {
using namespace clang;
class Slang {
static LangOptions LangOpts;
static CodeGenOptions CodeGenOpts;
static bool GlobalInitialized;
static void GlobalInitialization();
static void LLVMErrorHandler(void *UserData, const std::string &Message);
private:
PragmaList mPragmas;
/* The diagnostics engine instance (for status reporting during compilation) */
llvm::OwningPtr<Diagnostic> mDiagnostics;
llvm::OwningPtr<DiagnosticBuffer> mDiagClient;
inline void createDiagnostic() {
mDiagClient.reset(new DiagnosticBuffer());
mDiagnostics.reset(new Diagnostic(mDiagClient.get()));
bool optionNotFound = mDiagnostics->setDiagnosticGroupMapping("implicit-function-declaration", clang::diag::MAP_ERROR);
assert(!optionNotFound && "Unable find option group implicit-function-declaration");
return;
}
/* The target being compiled for */
TargetOptions mTargetOpts;
llvm::OwningPtr<TargetInfo> mTarget;
void createTarget(const char* Triple, const char* CPU, const char** Features);
/**** Below is for parsing ****/
/* The file manager (for prepocessor doing the job such as header file search) */
llvm::OwningPtr<FileManager> mFileMgr;
inline void createFileManager() { mFileMgr.reset(new FileManager()); return; }
/* The source manager (responsible for the source code handling) */
llvm::OwningPtr<SourceManager> mSourceMgr; /* The source manager */
inline void createSourceManager() { mSourceMgr.reset(new SourceManager(*mDiagnostics)); return; }
/* The preprocessor (source code preprocessor) */
llvm::OwningPtr<Preprocessor> mPP;
void createPreprocessor();
/* The AST context (the context to hold long-lived AST nodes) */
llvm::OwningPtr<ASTContext> mASTContext;
inline void createASTContext() {
mASTContext.reset(new ASTContext(LangOpts,
*mSourceMgr,
*mTarget,
mPP->getIdentifierTable(),
mPP->getSelectorTable(),
mPP->getBuiltinInfo()));
return;
}
/* Context for RenderScript */
llvm::OwningPtr<RSContext> mRSContext;
inline void createRSContext() {
mRSContext.reset(new RSContext(mPP.get(),
mASTContext.get(),
mTarget.get()));
return;
}
/* The AST consumer, responsible for code generation */
llvm::OwningPtr<Backend> mBackend;
inline void createBackend() {
mBackend.reset(new Backend(*mDiagnostics,
CodeGenOpts,
mTargetOpts,
mPragmas,
mOS.take(),
mOutputType,
*mSourceMgr,
mAllowRSPrefix));
return;
}
inline void createRSBackend() {
mBackend.reset(new RSBackend(mRSContext.get(),
*mDiagnostics,
CodeGenOpts,
mTargetOpts,
mPragmas,
mOS.take(),
mOutputType,
*mSourceMgr,
mAllowRSPrefix));
return;
}
/* Input file name */
std::string mInputFileName;
std::string mOutputFileName;
SlangCompilerOutputTy mOutputType;
/* Output stream */
llvm::OwningPtr<llvm::raw_ostream> mOS;
bool mAllowRSPrefix;
public:
static const std::string TargetDescription;
static const llvm::Twine PragmaMetadataName;
Slang(const char* Triple, const char* CPU, const char** Features);
bool setInputSource(llvm::StringRef inputFile, const char* text, size_t textLength);
bool setInputSource(llvm::StringRef inputFile);
void setOutputType(SlangCompilerOutputTy outputType);
inline bool setOutput(FILE* stream) {
if(stream == NULL)
return false;
mOS.reset( new llvm::raw_fd_ostream(fileno(stream), /* shouldClose */false) );
return true;
}
bool setOutput(const char* outputFile);
inline void allowRSPrefix() {
mAllowRSPrefix = true;
}
int compile();
bool reflectToJava(const char* outputPackageName);
bool reflectToJavaPath(const char* outputPathName);
inline const char* getErrorMessage() {
return mDiagClient->str().c_str();
}
void getPragmas(size_t* actualStringCount, size_t maxStringCount, char** strings);
/* Reset the slang compiler state such that it can be reused to compile another file */
inline void reset() {
/* Seems there's no way to clear the diagnostics. We just re-create it. */
createDiagnostic();
mOutputType = SlangCompilerOutput_Default;
return;
}
~Slang();
}; /* class Slang */
} /* namespace slang */
#endif /* _SLANG_COMPILER_SLANG_HPP */