slang_backend.cpp revision 1fd8579fe65b13a26cfaad12d056d2fc9b46475a
1#include "slang.hpp"
2#include "slang_backend.hpp"
3
4#include "llvm/Module.h"                /* for class llvm::Module */
5#include "llvm/Metadata.h"              /* for class llvm::NamedMDNode */
6#include "llvm/LLVMContext.h"           /* for llvm::getGlobalContext() */
7
8#include "llvm/Target/TargetMachine.h"  /* for class llvm::TargetMachine and llvm::TargetMachine::AssemblyFile */
9#include "llvm/Target/TargetOptions.h"  /* for
10                                         *  variable bool llvm::UseSoftFloat
11                                         *  FloatABI::ABIType llvm::FloatABIType
12                                         *  bool llvm::NoZerosInBSS
13                                         */
14#include "llvm/Target/TargetRegistry.h"     /* for class llvm::TargetRegistry */
15#include "llvm/Target/SubtargetFeature.h"   /* for class llvm::SubtargetFeature */
16
17#include "llvm/CodeGen/RegAllocRegistry.h"      /* for class llvm::RegisterRegAlloc */
18#include "llvm/CodeGen/SchedulerRegistry.h"     /* for class llvm::RegisterScheduler and llvm::createDefaultScheduler() */
19
20#include "llvm/Assembly/PrintModulePass.h"      /* for function createPrintModulePass() */
21#include "llvm/Bitcode/ReaderWriter.h"          /* for function createBitcodeWriterPass() */
22
23#include "clang/AST/Decl.h"             /* for class clang::*Decl */
24#include "clang/AST/DeclGroup.h"        /* for class clang::DeclGroupRef */
25#include "clang/AST/ASTContext.h"       /* for class clang::ASTContext */
26
27#include "clang/Basic/TargetInfo.h"     /* for class clang::TargetInfo */
28#include "clang/Basic/Diagnostic.h"     /* for class clang::Diagnostic */
29#include "clang/Basic/TargetOptions.h"  /* for class clang::TargetOptions */
30
31#include "clang/Frontend/FrontendDiagnostic.h"      /* for clang::diag::* */
32
33#include "clang/CodeGen/ModuleBuilder.h"    /* for class clang::CodeGenerator */
34#include "clang/CodeGen/CodeGenOptions.h"   /* for class clang::CodeGenOptions */
35
36namespace slang {
37
38bool Backend::CreateCodeGenPasses() {
39    if(mOutputType != SlangCompilerOutput_Assembly && mOutputType != SlangCompilerOutput_Obj)
40        return true;
41
42    /* Now we add passes for code emitting */
43    if(mCodeGenPasses) {
44        return true;
45    } else {
46        mCodeGenPasses = new llvm::FunctionPassManager(mpModule);
47        mCodeGenPasses->add(new llvm::TargetData(*mpTargetData));
48    }
49
50    /* Create the TargetMachine for generating code. */
51    std::string Triple = mpModule->getTargetTriple();
52
53    std::string Error;
54    const llvm::Target* TargetInfo = llvm::TargetRegistry::lookupTarget(Triple, Error);
55    if(TargetInfo == NULL) {
56        mDiags.Report(clang::diag::err_fe_unable_to_create_target) << Error;
57        return false;
58    }
59
60    llvm::NoFramePointerElim = mCodeGenOpts.DisableFPElim;
61
62    /*
63     * Use hardware FPU.
64     *
65     * FIXME: Need to detect the CPU capability and decide whether to use softfp. To use softfp, change following 2 lines to
66     *
67     *  llvm::FloatABIType = llvm::FloatABI::Soft;
68     *  llvm::UseSoftFloat = true;
69     */
70    llvm::FloatABIType = llvm::FloatABI::Hard;
71    llvm::UseSoftFloat = false;
72
73    llvm::TargetMachine::setRelocationModel(llvm::Reloc::Static);   /* ACC needs all unknown symbols resolved at compilation time.
74                                                                        So we don't need any relocation model. */
75
76    /* The target with pointer size greater than 32 (e.g. x86_64 architecture) may need large data address model */
77    if(mpTargetData->getPointerSizeInBits() > 32)
78        llvm::TargetMachine::setCodeModel(llvm::CodeModel::Medium);
79    else
80        llvm::TargetMachine::setCodeModel(llvm::CodeModel::Small);  /* This is set for the linker (specify how large of the virtual addresses
81                                                                        we can access for all unknown symbols.) */
82
83    /* setup feature string */
84    std::string FeaturesStr;
85    if(mTargetOpts.CPU.size() || mTargetOpts.Features.size()) {
86        llvm::SubtargetFeatures Features;
87
88        Features.setCPU(mTargetOpts.CPU);
89
90        for(std::vector<std::string>::const_iterator it = mTargetOpts.Features.begin();
91            it != mTargetOpts.Features.end();
92            it++)
93            Features.AddFeature(*it);
94
95        FeaturesStr = Features.getString();
96    }
97    llvm::TargetMachine *TM = TargetInfo->createTargetMachine(Triple, FeaturesStr);
98
99    /* Register scheduler */
100    llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
101
102    /* Register allocation policy:
103     *  createLocalRegisterAllocator: fast but bad quality
104     *  createLinearScanRegisterAllocator: not so fast but good quality
105     */
106    llvm::RegisterRegAlloc::setDefault((mCodeGenOpts.OptimizationLevel == 0) ? llvm::createLocalRegisterAllocator : llvm::createLinearScanRegisterAllocator);
107
108    llvm::CodeGenOpt::Level OptLevel = llvm::CodeGenOpt::Default;
109    if(mCodeGenOpts.OptimizationLevel == 0)
110        OptLevel = llvm::CodeGenOpt::None;
111    else if(mCodeGenOpts.OptimizationLevel == 3)
112        OptLevel = llvm::CodeGenOpt::Aggressive;
113
114    llvm::TargetMachine::CodeGenFileType CGFT = llvm::TargetMachine::CGFT_AssemblyFile;;
115    if(mOutputType == SlangCompilerOutput_Obj)
116        CGFT = llvm::TargetMachine::CGFT_ObjectFile;
117    if(TM->addPassesToEmitFile(*mCodeGenPasses, FormattedOutStream, CGFT, OptLevel)) {
118        mDiags.Report(clang::diag::err_fe_unable_to_interface_with_target);
119        return false;
120    }
121
122    return true;
123}
124
125Backend::Backend(Diagnostic &Diags,
126                 const CodeGenOptions& CodeGenOpts,
127                 const TargetOptions& TargetOpts,
128                 const PragmaList& Pragmas,
129                 llvm::raw_ostream* OS,
130                 SlangCompilerOutputTy OutputType,
131                 SourceManager &SourceMgr,
132                 bool AllowRSPrefix) :
133    ASTConsumer(),
134    mLLVMContext(llvm::getGlobalContext()),
135    mDiags(Diags),
136    mCodeGenOpts(CodeGenOpts),
137    mTargetOpts(TargetOpts),
138    mPragmas(Pragmas),
139    mpOS(OS),
140    mOutputType(OutputType),
141    mpModule(NULL),
142    mpTargetData(NULL),
143    mGen(NULL),
144    mPerFunctionPasses(NULL),
145    mPerModulePasses(NULL),
146    mCodeGenPasses(NULL),
147    mSourceMgr(SourceMgr),
148    mAllowRSPrefix(AllowRSPrefix)
149{
150    FormattedOutStream.setStream(*mpOS, llvm::formatted_raw_ostream::PRESERVE_STREAM);
151    mGen = CreateLLVMCodeGen(mDiags, "", mCodeGenOpts, mLLVMContext);
152    return;
153}
154
155void Backend::Initialize(ASTContext &Ctx) {
156    mGen->Initialize(Ctx);
157
158    mpModule = mGen->GetModule();
159    mpTargetData = new llvm::TargetData(Slang::TargetDescription);
160
161    return;
162}
163
164void Backend::HandleTopLevelDecl(DeclGroupRef D) {
165    /* Disallow user-defined functions with prefix "rs" */
166    if (!mAllowRSPrefix) {
167        DeclGroupRef::iterator it;
168        for (it = D.begin(); it != D.end(); it++) {
169            FunctionDecl *FD = dyn_cast<FunctionDecl>(*it);
170            if (!FD || !FD->isThisDeclarationADefinition()) continue;
171            if (FD->getName().startswith("rs")) {
172                mDiags.Report(FullSourceLoc(FD->getLocStart(), mSourceMgr),
173                              mDiags.getCustomDiagID(Diagnostic::Error, "invalid function name prefix, \"rs\" is reserved: '%0'")) << FD->getNameAsString();
174            }
175        }
176    }
177
178    mGen->HandleTopLevelDecl(D);
179    return;
180}
181
182void Backend::HandleTranslationUnit(ASTContext& Ctx) {
183    mGen->HandleTranslationUnit(Ctx);
184
185    /*
186     * Here, we complete a translation unit (whole translation unit is now in LLVM IR).
187     *  Now, interact with LLVM backend to generate actual machine code (asm or machine
188     *  code, whatever.)
189     */
190
191    if(!mpModule || !mpTargetData)  /* Silently ignore if we weren't initialized for some reason. */
192        return;
193
194    llvm::Module* M = mGen->ReleaseModule();
195    if(!M) {
196        /* The module has been released by IR gen on failures, do not double free. */
197        mpModule = NULL;
198        return;
199    }
200
201    assert(mpModule == M && "Unexpected module change during LLVM IR generation");
202
203    /* Insert #pragma information into metadata section of module */
204    if(!mPragmas.empty()) {
205        llvm::NamedMDNode* PragmaMetadata = llvm::NamedMDNode::Create(mLLVMContext, Slang::PragmaMetadataName, NULL, 0, mpModule);
206        for(PragmaList::const_iterator it = mPragmas.begin();
207            it != mPragmas.end();
208            it++)
209        {
210            llvm::SmallVector<llvm::Value*, 2> Pragma;
211            /* Name goes first */
212            Pragma.push_back(llvm::MDString::get(mLLVMContext, it->first));
213            /* And then value */
214            Pragma.push_back(llvm::MDString::get(mLLVMContext, it->second));
215            /* Create MDNode and insert into PragmaMetadata */
216            PragmaMetadata->addOperand( llvm::MDNode::get(mLLVMContext, Pragma.data(), Pragma.size()) );
217        }
218    }
219
220    HandleTranslationUnitEx(Ctx);
221
222    /* Create passes for optimization and code emission */
223
224    /* Create and run per-function passes */
225    CreateFunctionPasses();
226    if(mPerFunctionPasses) {
227        mPerFunctionPasses->doInitialization();
228
229        for(llvm::Module::iterator I = mpModule->begin();
230            I != mpModule->end();
231            I++)
232            if(!I->isDeclaration())
233                mPerFunctionPasses->run(*I);
234
235        mPerFunctionPasses->doFinalization();
236    }
237
238
239    /* Create and run module passes */
240    CreateModulePasses();
241    if(mPerModulePasses)
242        mPerModulePasses->run(*mpModule);
243
244    switch(mOutputType) {
245        case SlangCompilerOutput_Assembly:
246        case SlangCompilerOutput_Obj:
247            if(!CreateCodeGenPasses())
248                return;
249
250            mCodeGenPasses->doInitialization();
251
252            for(llvm::Module::iterator I = mpModule->begin();
253                I != mpModule->end();
254                I++)
255                if(!I->isDeclaration())
256                    mCodeGenPasses->run(*I);
257
258            mCodeGenPasses->doFinalization();
259        break;
260
261        case SlangCompilerOutput_LL:
262        {
263            llvm::PassManager* LLEmitPM = new llvm::PassManager();
264            LLEmitPM->add(llvm::createPrintModulePass(&FormattedOutStream));
265            LLEmitPM->run(*mpModule);
266        }
267        break;
268
269        case SlangCompilerOutput_Bitcode:
270        {
271            llvm::PassManager* BCEmitPM = new llvm::PassManager();
272            BCEmitPM->add(llvm::createBitcodeWriterPass(FormattedOutStream));
273            BCEmitPM->run(*mpModule);
274        }
275        break;
276
277        case SlangCompilerOutput_Nothing:
278            return;
279        break;
280
281        default:
282            assert(false && "Unknown output type");
283        break;
284    }
285
286    FormattedOutStream.flush();
287
288    return;
289}
290
291void Backend::HandleTagDeclDefinition(TagDecl* D) {
292    mGen->HandleTagDeclDefinition(D);
293    return;
294}
295
296void Backend::CompleteTentativeDefinition(VarDecl* D) {
297    mGen->CompleteTentativeDefinition(D);
298    return;
299}
300
301Backend::~Backend() {
302    if(mpModule)
303        delete mpModule;
304    if(mpTargetData)
305        delete mpTargetData;
306    if(mGen)
307        delete mGen;
308    if(mPerFunctionPasses)
309        delete mPerFunctionPasses;
310    if(mPerModulePasses)
311        delete mPerModulePasses;
312    if(mCodeGenPasses)
313        delete mCodeGenPasses;
314    return;
315}
316
317}   /* namespace slang */
318