blob: 4c1c8af43da0e724f7eb94bfb9f8b55cf03d033b [file] [log] [blame]
#ifndef _SLANG_COMPILER_BACKEND_HPP
# define _SLANG_COMPILER_BACKEND_HPP
#include "libslang.h"
#include "slang_pragma_recorder.hpp"
#include "llvm/PassManager.h" /* for class llvm::PassManager and llvm::FunctionPassManager */
#include "llvm/Target/TargetData.h" /* for class llvm::TargetData */
#include "llvm/Support/StandardPasses.h" /* for function llvm::createStandardFunctionPasses() and llvm::createStandardModulePasses() */
#include "llvm/Support/FormattedStream.h" /* for class llvm::formatted_raw_ostream */
#include "clang/AST/ASTConsumer.h" /* for class clang::ASTConsumer */
#include "clang/CodeGen/CodeGenOptions.h" /* for class clang::CodeGenOptions */
#include "clang/Basic/SourceManager.h" /* for class clang::SourceManager */
namespace llvm {
class LLVMContext;
class NamedMDNode;
class raw_ostream;
class Module;
} /* namespace llvm */
namespace clang {
class ASTConsumer;
class Diagnostic;
class TargetOptions;
class PragmaList;
class CodeGenerator;
class ASTContext;
class DeclGroupRef;
class TagDecl;
class VarDecl;
} /* namespace clang */
namespace slang {
using namespace clang;
class Backend : public ASTConsumer {
private:
const CodeGenOptions& mCodeGenOpts;
const TargetOptions& mTargetOpts;
SourceManager& mSourceMgr;
bool mAllowRSPrefix;
/* Output stream */
llvm::raw_ostream* mpOS;
SlangCompilerOutputTy mOutputType;
llvm::TargetData* mpTargetData;
/* The @Gen here help us to translate AST using in Clang to LLVM IR */
CodeGenerator* mGen;
/* Passes */
llvm::FunctionPassManager* mPerFunctionPasses; /* passes apply on function scope in a translation unit */
llvm::PassManager* mPerModulePasses; /* passes apply on module scope */
llvm::FunctionPassManager* mCodeGenPasses; /* passes for code emission */
llvm::formatted_raw_ostream FormattedOutStream;
inline void CreateFunctionPasses() {
if(!mPerFunctionPasses) {
mPerFunctionPasses = new llvm::FunctionPassManager(mpModule);
mPerFunctionPasses->add(new llvm::TargetData(*mpTargetData));
llvm::createStandardFunctionPasses(mPerFunctionPasses, mCodeGenOpts.OptimizationLevel);
}
return;
}
inline void CreateModulePasses() {
if(!mPerModulePasses) {
/* inline passes */
mPerModulePasses = new llvm::PassManager();
mPerModulePasses->add(new llvm::TargetData(*mpTargetData));
llvm::createStandardModulePasses(mPerModulePasses,
mCodeGenOpts.OptimizationLevel,
mCodeGenOpts.OptimizeSize,
mCodeGenOpts.UnitAtATime,
mCodeGenOpts.UnrollLoops,
/* SimplifyLibCalls */true, /* Some libc functions will be replaced
* by the LLVM built-in optimized function (e.g. strcmp)
*/
/* HaveExceptions */false,
/* InliningPass */NULL);
}
/*
* llvm::createStandardFunctionPasses and llvm::createStandardModulePasses insert lots of optimization passes for
* the code generator. For the conventional desktop PC which memory resources and computation power is relative
* large, doing lots optimization as possible is reasonible and feasible. However, on the mobile device or embedded
* system, this may cause some problem due to the hardware resources limitation. So they need further refine.
*/
return;
}
bool CreateCodeGenPasses();
protected:
llvm::Module* mpModule;
llvm::LLVMContext& mLLVMContext;
const PragmaList& mPragmas;
Diagnostic &mDiags;
/* Extra handler for subclass to handle translation unit before emission */
virtual void HandleTranslationUnitEx(ASTContext& Ctx) { return; }
public:
Backend(Diagnostic &Diags,
const CodeGenOptions& CodeGenOpts,
const TargetOptions& TargetOpts,
const PragmaList& Pragmas,
llvm::raw_ostream* OS,
SlangCompilerOutputTy OutputType,
SourceManager& SourceMgr,
bool AllowRSPrefix);
/*
* Initialize - This is called to initialize the consumer, providing the
* ASTContext.
*/
virtual void Initialize(ASTContext &Ctx);
/*
* HandleTopLevelDecl - Handle the specified top-level declaration. This is
* called by the parser to process every top-level Decl*. Note that D can be
* the head of a chain of Decls (e.g. for `int a, b` the chain will have two
* elements). Use Decl::getNextDeclarator() to walk the chain.
*/
virtual void HandleTopLevelDecl(DeclGroupRef D);
/*
* HandleTranslationUnit - This method is called when the ASTs for entire
* translation unit have been parsed.
*/
virtual void HandleTranslationUnit(ASTContext& Ctx);
/*
* HandleTagDeclDefinition - This callback is invoked each time a TagDecl
* (e.g. struct, union, enum, class) is completed. This allows the client to
* hack on the type, which can occur at any point in the file (because these
* can be defined in declspecs).
*/
virtual void HandleTagDeclDefinition(TagDecl* D);
/*
* CompleteTentativeDefinition - Callback invoked at the end of a translation
* unit to notify the consumer that the given tentative definition should be
* completed.
*/
virtual void CompleteTentativeDefinition(VarDecl* D);
virtual ~Backend();
};
} /* namespace slang */
#endif /* _SLANG_COMPILER_BACKEND_HPP */