Backend.cpp revision 05be040fdd9fa9d23259d6b6a4aaf4f2aca9c9f2
1#include "Backend.h"
2
3#include <cassert>
4#include <string>
5#include <vector>
6
7#include "clang/AST/ASTContext.h"
8#include "clang/AST/Decl.h"
9#include "clang/AST/DeclGroup.h"
10
11#include "clang/Basic/Diagnostic.h"
12#include "clang/Basic/TargetInfo.h"
13#include "clang/Basic/TargetOptions.h"
14
15#include "clang/CodeGen/ModuleBuilder.h"
16
17#include "clang/Frontend/CodeGenOptions.h"
18#include "clang/Frontend/FrontendDiagnostic.h"
19
20#include "llvm/Assembly/PrintModulePass.h"
21
22#include "llvm/Bitcode/ReaderWriter.h"
23
24#include "llvm/CodeGen/RegAllocRegistry.h"
25#include "llvm/CodeGen/SchedulerRegistry.h"
26
27#include "llvm/Instructions.h"
28#include "llvm/LLVMContext.h"
29#include "llvm/Module.h"
30#include "llvm/Metadata.h"
31
32#include "llvm/Support/Casting.h"
33#include "llvm/Support/InstIterator.h"
34
35#include "llvm/Target/TargetData.h"
36#include "llvm/Target/TargetMachine.h"
37#include "llvm/Target/TargetOptions.h"
38#include "llvm/Target/TargetRegistry.h"
39#include "llvm/Target/SubtargetFeature.h"
40
41namespace ndkpc {
42
43void Backend::CreateFunctionPasses() {
44  if (!mpPerFunctionPasses) {
45    mpPerFunctionPasses = new llvm::FunctionPassManager(mpModule);
46    mpPerFunctionPasses->add(new llvm::TargetData(mpModule));
47
48    // FIXME REMOVE
49    //llvm::createStandardFunctionPasses(mpPerFunctionPasses,
50    //                                   mCodeGenOpts.OptimizationLevel);
51    llvm::PassManagerBuilder PMBuilder;
52    PMBuilder.OptLevel = mCodeGenOpts.OptimizationLevel;
53    PMBuilder.populateFunctionPassManager(*mpPerFunctionPasses);
54  }
55  return;
56}
57
58void Backend::CreateModulePasses() {
59  if (!mpPerModulePasses) {
60	  mpPerModulePasses = new llvm::PassManager();
61	  mpPerModulePasses->add(new llvm::TargetData(mpModule));
62
63	  llvm::PassManagerBuilder PMBuilder;
64	  PMBuilder.OptLevel = mCodeGenOpts.OptimizationLevel;
65	  PMBuilder.SizeLevel = mCodeGenOpts.OptimizeSize;
66	  if (mCodeGenOpts.UnitAtATime) {
67		  PMBuilder.DisableUnitAtATime = 0;
68	  } else {
69		  PMBuilder.DisableUnitAtATime = 1;
70	  }
71
72	  if (mCodeGenOpts.UnrollLoops) {
73		  PMBuilder.DisableUnrollLoops = 0;
74	  } else {
75		  PMBuilder.DisableUnrollLoops = 1;
76	  }
77
78	  PMBuilder.DisableSimplifyLibCalls = false;
79	  PMBuilder.populateModulePassManager(*mpPerModulePasses);
80  }
81  return;
82}
83
84bool Backend::CreateCodeGenPasses() {
85  if ((mOT != Compiler::OT_Assembly) && (mOT != Compiler::OT_Object))
86    return true;
87
88  // Now we add passes for code emitting
89  if (mpCodeGenPasses) {
90    return true;
91  } else {
92    mpCodeGenPasses = new llvm::FunctionPassManager(mpModule);
93    mpCodeGenPasses->add(new llvm::TargetData(mpModule));
94  }
95
96  // Create the TargetMachine for generating code.
97  std::string Triple = mpModule->getTargetTriple();
98
99  std::string Error;
100  const llvm::Target* TargetInfo =
101      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  // Use hardware FPU.
110  //
111  // FIXME: Need to detect the CPU capability and decide whether to use softfp.
112  // To use softfp, change following 2 lines to
113  //
114  //  llvm::FloatABIType = llvm::FloatABI::Soft;
115  //  llvm::UseSoftFloat = true;
116  llvm::FloatABIType = llvm::FloatABI::Hard;
117  llvm::UseSoftFloat = false;
118
119  // BCC needs all unknown symbols resolved at compilation time. So we don't
120  // need any relocation model.
121  llvm::TargetMachine::setRelocationModel(llvm::Reloc::Static);
122
123
124  // This is set for the linker (specify how large of the virtual addresses we
125  // can access for all unknown symbols.)
126  if (mpModule->getPointerSize() == llvm::Module::Pointer32)
127    llvm::TargetMachine::setCodeModel(llvm::CodeModel::Small);
128  else
129    // The target may have pointer size greater than 32 (e.g. x86_64
130    // architecture) may need large data address model
131    llvm::TargetMachine::setCodeModel(llvm::CodeModel::Medium);
132
133  // Setup feature string
134  std::string FeaturesStr;
135  if (mTargetOpts.CPU.size() || mTargetOpts.Features.size()) {
136    llvm::SubtargetFeatures Features;
137
138    Features.setCPU(mTargetOpts.CPU);
139
140    for (std::vector<std::string>::const_iterator
141             I = mTargetOpts.Features.begin(), E = mTargetOpts.Features.end();
142         I != E;
143         I++)
144      Features.AddFeature(*I);
145
146    FeaturesStr = Features.getString();
147  }
148  llvm::TargetMachine *TM =
149      TargetInfo->createTargetMachine(Triple, FeaturesStr);
150
151  // Register scheduler
152  llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
153
154  // Register allocation policy:
155  //  createFastRegisterAllocator: fast but bad quality
156  //  createLinearScanRegisterAllocator: not so fast but good quality
157  llvm::RegisterRegAlloc::setDefault((mCodeGenOpts.OptimizationLevel == 0) ?
158                                     llvm::createFastRegisterAllocator :
159                                     llvm::createLinearScanRegisterAllocator);
160
161  llvm::CodeGenOpt::Level OptLevel = llvm::CodeGenOpt::Default;
162  if (mCodeGenOpts.OptimizationLevel == 0)
163    OptLevel = llvm::CodeGenOpt::None;
164  else if (mCodeGenOpts.OptimizationLevel == 3)
165    OptLevel = llvm::CodeGenOpt::Aggressive;
166
167  llvm::TargetMachine::CodeGenFileType CGFT =
168      llvm::TargetMachine::CGFT_AssemblyFile;
169  if (mOT == Compiler::OT_Object)
170    CGFT = llvm::TargetMachine::CGFT_ObjectFile;
171  if (TM->addPassesToEmitFile(*mpCodeGenPasses, FormattedOutStream,
172                              CGFT, OptLevel)) {
173    mDiags.Report(clang::diag::err_fe_unable_to_interface_with_target);
174    return false;
175  }
176
177  return true;
178}
179
180Backend::Backend(const clang::CodeGenOptions &CodeGenOpts,
181                 const clang::TargetOptions &TargetOpts,
182                 clang::Diagnostic *Diags,
183                 llvm::raw_ostream *OS,
184                 Compiler::OutputType OT)
185    : ASTConsumer(),
186      mCodeGenOpts(CodeGenOpts),
187      mTargetOpts(TargetOpts),
188      mLLVMContext(llvm::getGlobalContext()),
189      mDiags(*Diags),
190      mpModule(NULL),
191      mpOS(OS),
192      mOT(OT),
193      mpGen(NULL),
194      mpPerFunctionPasses(NULL),
195      mpPerModulePasses(NULL),
196      mpCodeGenPasses(NULL) {
197  FormattedOutStream.setStream(*mpOS,
198                               llvm::formatted_raw_ostream::PRESERVE_STREAM);
199  mpGen = CreateLLVMCodeGen(mDiags, "", mCodeGenOpts, mLLVMContext);
200  return;
201}
202
203void Backend::Initialize(clang::ASTContext &Ctx) {
204  mpGen->Initialize(Ctx);
205  mpModule = mpGen->GetModule();
206  return;
207}
208
209void Backend::HandleTopLevelDecl(clang::DeclGroupRef D) {
210  mpGen->HandleTopLevelDecl(D);
211  return;
212}
213
214void Backend::HandleTranslationUnit(clang::ASTContext &Ctx) {
215  mpGen->HandleTranslationUnit(Ctx);
216
217  // Here, we complete a translation unit (whole translation unit is now in LLVM
218  // IR). Now, interact with LLVM backend to generate actual machine code (asm
219  // or machine code, whatever.)
220
221  // Silently ignore if we weren't initialized for some reason.
222  if (!mpModule)
223    return;
224
225  llvm::Module *M = mpGen->ReleaseModule();
226  if (!M) {
227    // The module has been released by IR gen on failures, do not double free.
228    mpModule = NULL;
229    return;
230  }
231
232  assert(mpModule == M &&
233              "Unexpected module change during LLVM IR generation");
234
235  // Handle illigal CallSite
236  for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end();
237       I != E;
238       ++I) {
239    for (llvm::inst_iterator i = llvm::inst_begin(*I), e = llvm::inst_end(*I);
240         i != e;
241         ++i) {
242      if (llvm::CallInst* CallInst = llvm::dyn_cast<llvm::CallInst>(&*i)) {
243        if (CallInst->isInlineAsm()) {
244          // TODO: Should we reflect source location information to diagnostic
245          //       class and show to users?
246          llvm::errs() << "Inline assembly is illigal. Please don't use it." << "\n";
247          exit(1);
248        }
249      }
250    }
251  }
252
253  // Create and run per-function passes
254  CreateFunctionPasses();
255  if (mpPerFunctionPasses) {
256    mpPerFunctionPasses->doInitialization();
257
258    for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end();
259         I != E;
260         I++)
261      if (!I->isDeclaration())
262        mpPerFunctionPasses->run(*I);
263
264    mpPerFunctionPasses->doFinalization();
265  }
266
267  // Create and run module passes
268  CreateModulePasses();
269  if (mpPerModulePasses)
270    mpPerModulePasses->run(*mpModule);
271
272  switch (mOT) {
273    case Compiler::OT_Assembly:
274    case Compiler::OT_Object: {
275      if (!CreateCodeGenPasses())
276        return;
277
278      mpCodeGenPasses->doInitialization();
279
280      for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end();
281          I != E;
282          I++)
283        if (!I->isDeclaration())
284          mpCodeGenPasses->run(*I);
285
286      mpCodeGenPasses->doFinalization();
287      break;
288    }
289    case Compiler::OT_LLVMAssembly: {
290      llvm::PassManager *LLEmitPM = new llvm::PassManager();
291      LLEmitPM->add(llvm::createPrintModulePass(&FormattedOutStream));
292      LLEmitPM->run(*mpModule);
293      break;
294    }
295    case Compiler::OT_Bitcode: {
296      llvm::PassManager *BCEmitPM = new llvm::PassManager();
297      BCEmitPM->add(llvm::createBitcodeWriterPass(FormattedOutStream));
298      BCEmitPM->run(*mpModule);
299      break;
300    }
301    case Compiler::OT_Nothing: {
302      return;
303    }
304    default: {
305      assert(false && "Unknown output type");
306    }
307  }
308
309  FormattedOutStream.flush();
310  return;
311}
312
313void Backend::HandleTagDeclDefinition(clang::TagDecl *D) {
314  mpGen->HandleTagDeclDefinition(D);
315  return;
316}
317
318void Backend::CompleteTentativeDefinition(clang::VarDecl *D) {
319  mpGen->CompleteTentativeDefinition(D);
320  return;
321}
322
323Backend::~Backend() {
324  delete mpModule;
325  delete mpGen;
326  delete mpPerFunctionPasses;
327  delete mpPerModulePasses;
328  delete mpCodeGenPasses;
329  return;
330}
331
332}
333