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