slang_backend.cpp revision 6b22674f4ef0a6c689c589830f1c44f443520785
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    ASTConsumer(),
133    mLLVMContext(llvm::getGlobalContext()),
134    mDiags(Diags),
135    mCodeGenOpts(CodeGenOpts),
136    mTargetOpts(TargetOpts),
137    mPragmas(Pragmas),
138    mpOS(OS),
139    mOutputType(OutputType),
140    mpModule(NULL),
141    mpTargetData(NULL),
142    mGen(NULL),
143    mPerFunctionPasses(NULL),
144    mPerModulePasses(NULL),
145    mCodeGenPasses(NULL),
146    mSourceMgr(SourceMgr)
147{
148    FormattedOutStream.setStream(*mpOS, llvm::formatted_raw_ostream::PRESERVE_STREAM);
149    mGen = CreateLLVMCodeGen(mDiags, "", mCodeGenOpts, mLLVMContext);
150    return;
151}
152
153void Backend::Initialize(ASTContext &Ctx) {
154    mGen->Initialize(Ctx);
155
156    mpModule = mGen->GetModule();
157    mpTargetData = new llvm::TargetData(Slang::TargetDescription);
158
159    return;
160}
161
162void Backend::HandleTopLevelDecl(DeclGroupRef D) {
163    /* Disallow user-defined functions with prefix "rs" */
164    DeclGroupRef::iterator it;
165    for (it = D.begin(); it != D.end(); it++) {
166        FunctionDecl *FD = dyn_cast<FunctionDecl>(*it);
167        if (!FD || !FD->isThisDeclarationADefinition()) continue;
168        if (FD->getNameAsString().compare(0, 2, "rs") == 0) {
169            mDiags.Report(FullSourceLoc(FD->getLocStart(), mSourceMgr),
170                          mDiags.getCustomDiagID(Diagnostic::Error, "invalid function name prefix, \"rs\" is reserved: '%0'")) << FD->getNameAsString();
171        }
172    }
173
174    mGen->HandleTopLevelDecl(D);
175    return;
176}
177
178void Backend::HandleTranslationUnit(ASTContext& Ctx) {
179    mGen->HandleTranslationUnit(Ctx);
180
181    /*
182     * Here, we complete a translation unit (whole translation unit is now in LLVM IR).
183     *  Now, interact with LLVM backend to generate actual machine code (asm or machine
184     *  code, whatever.)
185     */
186
187    if(!mpModule || !mpTargetData)  /* Silently ignore if we weren't initialized for some reason. */
188        return;
189
190    llvm::Module* M = mGen->ReleaseModule();
191    if(!M) {
192        /* The module has been released by IR gen on failures, do not double free. */
193        mpModule = NULL;
194        return;
195    }
196
197    assert(mpModule == M && "Unexpected module change during LLVM IR generation");
198
199    /* Insert #pragma information into metadata section of module */
200    if(!mPragmas.empty()) {
201        llvm::NamedMDNode* PragmaMetadata = llvm::NamedMDNode::Create(mLLVMContext, Slang::PragmaMetadataName, NULL, 0, mpModule);
202        for(PragmaList::const_iterator it = mPragmas.begin();
203            it != mPragmas.end();
204            it++)
205        {
206            llvm::SmallVector<llvm::Value*, 2> Pragma;
207            /* Name goes first */
208            Pragma.push_back(llvm::MDString::get(mLLVMContext, it->first));
209            /* And then value */
210            Pragma.push_back(llvm::MDString::get(mLLVMContext, it->second));
211            /* Create MDNode and insert into PragmaMetadata */
212            PragmaMetadata->addOperand( llvm::MDNode::get(mLLVMContext, Pragma.data(), Pragma.size()) );
213        }
214    }
215
216    HandleTranslationUnitEx(Ctx);
217
218    /* Create passes for optimization and code emission */
219
220    /* Create and run per-function passes */
221    CreateFunctionPasses();
222    if(mPerFunctionPasses) {
223        mPerFunctionPasses->doInitialization();
224
225        for(llvm::Module::iterator I = mpModule->begin();
226            I != mpModule->end();
227            I++)
228            if(!I->isDeclaration())
229                mPerFunctionPasses->run(*I);
230
231        mPerFunctionPasses->doFinalization();
232    }
233
234
235    /* Create and run module passes */
236    CreateModulePasses();
237    if(mPerModulePasses)
238        mPerModulePasses->run(*mpModule);
239
240    switch(mOutputType) {
241        case SlangCompilerOutput_Assembly:
242        case SlangCompilerOutput_Obj:
243            if(!CreateCodeGenPasses())
244                return;
245
246            mCodeGenPasses->doInitialization();
247
248            for(llvm::Module::iterator I = mpModule->begin();
249                I != mpModule->end();
250                I++)
251                if(!I->isDeclaration())
252                    mCodeGenPasses->run(*I);
253
254            mCodeGenPasses->doFinalization();
255        break;
256
257        case SlangCompilerOutput_LL:
258        {
259            llvm::PassManager* LLEmitPM = new llvm::PassManager();
260            LLEmitPM->add(llvm::createPrintModulePass(&FormattedOutStream));
261            LLEmitPM->run(*mpModule);
262        }
263        break;
264
265        case SlangCompilerOutput_Bitcode:
266        {
267            llvm::PassManager* BCEmitPM = new llvm::PassManager();
268            BCEmitPM->add(llvm::createBitcodeWriterPass(FormattedOutStream));
269            BCEmitPM->run(*mpModule);
270        }
271        break;
272
273        case SlangCompilerOutput_Nothing:
274            return;
275        break;
276
277        default:
278            assert(false && "Unknown output type");
279        break;
280    }
281
282    FormattedOutStream.flush();
283
284    return;
285}
286
287void Backend::HandleTagDeclDefinition(TagDecl* D) {
288    mGen->HandleTagDeclDefinition(D);
289    return;
290}
291
292void Backend::CompleteTentativeDefinition(VarDecl* D) {
293    mGen->CompleteTentativeDefinition(D);
294    return;
295}
296
297Backend::~Backend() {
298    if(mpModule)
299        delete mpModule;
300    if(mpTargetData)
301        delete mpTargetData;
302    if(mGen)
303        delete mGen;
304    if(mPerFunctionPasses)
305        delete mPerFunctionPasses;
306    if(mPerModulePasses)
307        delete mPerModulePasses;
308    if(mCodeGenPasses)
309        delete mCodeGenPasses;
310    return;
311}
312
313}   /* namespace slang */
314