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