blob: 0000f389650525b576e928ef546535000c2f3c1a [file] [log] [blame]
#ifndef _SLANG_COMPILER_SLANG_H
#define _SLANG_COMPILER_SLANG_H
#include <cstdio>
#include <string>
#include <vector>
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringRef.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "slang_backend.h"
#include "slang_rs_context.h"
#include "slang_rs_backend.h"
#include "slang_pragma_recorder.h"
#include "slang_diagnostic_buffer.h"
namespace llvm {
class TargetInfo;
}
namespace clang {
class LangOptions;
class CodeGenOptions;
class TargetOptions;
}
namespace slang {
class Slang {
static clang::LangOptions LangOpts;
static clang::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<clang::Diagnostic> mDiagnostics;
llvm::OwningPtr<DiagnosticBuffer> mDiagClient;
inline void createDiagnostic() {
mDiagClient.reset(new DiagnosticBuffer());
mDiagnostics.reset(new clang::Diagnostic(mDiagClient.get()));
if (!mDiagnostics->setDiagnosticGroupMapping(
"implicit-function-declaration",
clang::diag::MAP_ERROR))
assert("Unable find option group implicit-function-declaration");
mDiagnostics->setDiagnosticMapping(
clang::diag::ext_typecheck_convert_discards_qualifiers,
clang::diag::MAP_ERROR);
return;
}
// The target being compiled for
clang::TargetOptions mTargetOpts;
llvm::OwningPtr<clang::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<clang::FileManager> mFileMgr;
inline void createFileManager() {
mFileMgr.reset(new clang::FileManager());
return;
}
// The source manager (responsible for the source code handling)
llvm::OwningPtr<clang::SourceManager> mSourceMgr;
inline void createSourceManager() {
mSourceMgr.reset(new clang::SourceManager(*mDiagnostics));
return;
}
// The preprocessor (source code preprocessor)
llvm::OwningPtr<clang::Preprocessor> mPP;
void createPreprocessor();
// The AST context (the context to hold long-lived AST nodes)
llvm::OwningPtr<clang::ASTContext> mASTContext;
inline void createASTContext() {
mASTContext.reset(new clang::ASTContext(LangOpts,
*mSourceMgr,
*mTarget,
mPP->getIdentifierTable(),
mPP->getSelectorTable(),
mPP->getBuiltinInfo(),
/* size_reserve */0));
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;
std::vector<std::string> mIncludePaths;
public:
static const std::string TargetDescription;
static const llvm::StringRef 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 addIncludePath(const char *path);
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();
// The package name that's really applied will be filled in realPackageName.
// bSize is the buffer realPackageName size.
bool reflectToJava(const char *outputPackageName,
char *realPackageName, int bSize);
bool reflectToJavaPath(const char *outputPathName);
inline const char *getErrorMessage() {
return mDiagClient->str().c_str();
}
void getPragmas(size_t *actualStringCount, size_t maxStringCount,
char **strings);
const char *exportFuncs();
// 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();
};
}
#endif // _SLANG_COMPILER_SLANG_H