• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2010-2012, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "slang_backend.h"
18 
19 #include <string>
20 #include <vector>
21 
22 #include "bcinfo/BitcodeWrapper.h"
23 
24 #include "clang/AST/ASTContext.h"
25 #include "clang/AST/Decl.h"
26 #include "clang/AST/DeclGroup.h"
27 
28 #include "clang/Basic/Diagnostic.h"
29 #include "clang/Basic/TargetInfo.h"
30 #include "clang/Basic/TargetOptions.h"
31 
32 #include "clang/CodeGen/ModuleBuilder.h"
33 
34 #include "clang/Frontend/CodeGenOptions.h"
35 #include "clang/Frontend/FrontendDiagnostic.h"
36 
37 #include "llvm/Assembly/PrintModulePass.h"
38 
39 #include "llvm/Bitcode/ReaderWriter.h"
40 
41 #include "llvm/CodeGen/RegAllocRegistry.h"
42 #include "llvm/CodeGen/SchedulerRegistry.h"
43 
44 #include "llvm/IR/LLVMContext.h"
45 #include "llvm/IR/Module.h"
46 #include "llvm/IR/Metadata.h"
47 
48 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
49 
50 #include "llvm/IR/DataLayout.h"
51 #include "llvm/Target/TargetMachine.h"
52 #include "llvm/Target/TargetOptions.h"
53 #include "llvm/Support/TargetRegistry.h"
54 
55 #include "llvm/MC/SubtargetFeature.h"
56 
57 #include "slang_assert.h"
58 #include "BitWriter_2_9/ReaderWriter_2_9.h"
59 #include "BitWriter_2_9_func/ReaderWriter_2_9_func.h"
60 #include "BitWriter_3_2/ReaderWriter_3_2.h"
61 
62 namespace slang {
63 
CreateFunctionPasses()64 void Backend::CreateFunctionPasses() {
65   if (!mPerFunctionPasses) {
66     mPerFunctionPasses = new llvm::FunctionPassManager(mpModule);
67     mPerFunctionPasses->add(new llvm::DataLayout(mpModule));
68 
69     llvm::PassManagerBuilder PMBuilder;
70     PMBuilder.OptLevel = mCodeGenOpts.OptimizationLevel;
71     PMBuilder.populateFunctionPassManager(*mPerFunctionPasses);
72   }
73   return;
74 }
75 
CreateModulePasses()76 void Backend::CreateModulePasses() {
77   if (!mPerModulePasses) {
78     mPerModulePasses = new llvm::PassManager();
79     mPerModulePasses->add(new llvm::DataLayout(mpModule));
80 
81     llvm::PassManagerBuilder PMBuilder;
82     PMBuilder.OptLevel = mCodeGenOpts.OptimizationLevel;
83     PMBuilder.SizeLevel = mCodeGenOpts.OptimizeSize;
84     PMBuilder.SizeLevel = mCodeGenOpts.OptimizeSize;
85     if (mCodeGenOpts.UnitAtATime) {
86       PMBuilder.DisableUnitAtATime = 0;
87     } else {
88       PMBuilder.DisableUnitAtATime = 1;
89     }
90 
91     if (mCodeGenOpts.UnrollLoops) {
92       PMBuilder.DisableUnrollLoops = 0;
93     } else {
94       PMBuilder.DisableUnrollLoops = 1;
95     }
96 
97     PMBuilder.DisableSimplifyLibCalls = false;
98     PMBuilder.populateModulePassManager(*mPerModulePasses);
99   }
100   return;
101 }
102 
CreateCodeGenPasses()103 bool Backend::CreateCodeGenPasses() {
104   if ((mOT != Slang::OT_Assembly) && (mOT != Slang::OT_Object))
105     return true;
106 
107   // Now we add passes for code emitting
108   if (mCodeGenPasses) {
109     return true;
110   } else {
111     mCodeGenPasses = new llvm::FunctionPassManager(mpModule);
112     mCodeGenPasses->add(new llvm::DataLayout(mpModule));
113   }
114 
115   // Create the TargetMachine for generating code.
116   std::string Triple = mpModule->getTargetTriple();
117 
118   std::string Error;
119   const llvm::Target* TargetInfo =
120       llvm::TargetRegistry::lookupTarget(Triple, Error);
121   if (TargetInfo == NULL) {
122     mDiagEngine.Report(clang::diag::err_fe_unable_to_create_target) << Error;
123     return false;
124   }
125 
126   // Target Machine Options
127   llvm::TargetOptions Options;
128 
129   Options.NoFramePointerElim = mCodeGenOpts.DisableFPElim;
130 
131   // Use hardware FPU.
132   //
133   // FIXME: Need to detect the CPU capability and decide whether to use softfp.
134   // To use softfp, change following 2 lines to
135   //
136   // Options.FloatABIType = llvm::FloatABI::Soft;
137   // Options.UseSoftFloat = true;
138   Options.FloatABIType = llvm::FloatABI::Hard;
139   Options.UseSoftFloat = false;
140 
141   // BCC needs all unknown symbols resolved at compilation time. So we don't
142   // need any relocation model.
143   llvm::Reloc::Model RM = llvm::Reloc::Static;
144 
145   // This is set for the linker (specify how large of the virtual addresses we
146   // can access for all unknown symbols.)
147   llvm::CodeModel::Model CM;
148   if (mpModule->getPointerSize() == llvm::Module::Pointer32) {
149     CM = llvm::CodeModel::Small;
150   } else {
151     // The target may have pointer size greater than 32 (e.g. x86_64
152     // architecture) may need large data address model
153     CM = llvm::CodeModel::Medium;
154   }
155 
156   // Setup feature string
157   std::string FeaturesStr;
158   if (mTargetOpts.CPU.size() || mTargetOpts.Features.size()) {
159     llvm::SubtargetFeatures Features;
160 
161     for (std::vector<std::string>::const_iterator
162              I = mTargetOpts.Features.begin(), E = mTargetOpts.Features.end();
163          I != E;
164          I++)
165       Features.AddFeature(*I);
166 
167     FeaturesStr = Features.getString();
168   }
169 
170   llvm::TargetMachine *TM =
171     TargetInfo->createTargetMachine(Triple, mTargetOpts.CPU, FeaturesStr,
172                                     Options, RM, CM);
173 
174   // Register scheduler
175   llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
176 
177   // Register allocation policy:
178   //  createFastRegisterAllocator: fast but bad quality
179   //  createGreedyRegisterAllocator: not so fast but good quality
180   llvm::RegisterRegAlloc::setDefault((mCodeGenOpts.OptimizationLevel == 0) ?
181                                      llvm::createFastRegisterAllocator :
182                                      llvm::createGreedyRegisterAllocator);
183 
184   llvm::CodeGenOpt::Level OptLevel = llvm::CodeGenOpt::Default;
185   if (mCodeGenOpts.OptimizationLevel == 0) {
186     OptLevel = llvm::CodeGenOpt::None;
187   } else if (mCodeGenOpts.OptimizationLevel == 3) {
188     OptLevel = llvm::CodeGenOpt::Aggressive;
189   }
190 
191   llvm::TargetMachine::CodeGenFileType CGFT =
192       llvm::TargetMachine::CGFT_AssemblyFile;
193   if (mOT == Slang::OT_Object) {
194     CGFT = llvm::TargetMachine::CGFT_ObjectFile;
195   }
196   if (TM->addPassesToEmitFile(*mCodeGenPasses, FormattedOutStream,
197                               CGFT, OptLevel)) {
198     mDiagEngine.Report(clang::diag::err_fe_unable_to_interface_with_target);
199     return false;
200   }
201 
202   return true;
203 }
204 
Backend(clang::DiagnosticsEngine * DiagEngine,const clang::CodeGenOptions & CodeGenOpts,const clang::TargetOptions & TargetOpts,PragmaList * Pragmas,llvm::raw_ostream * OS,Slang::OutputType OT)205 Backend::Backend(clang::DiagnosticsEngine *DiagEngine,
206                  const clang::CodeGenOptions &CodeGenOpts,
207                  const clang::TargetOptions &TargetOpts,
208                  PragmaList *Pragmas,
209                  llvm::raw_ostream *OS,
210                  Slang::OutputType OT)
211     : ASTConsumer(),
212       mTargetOpts(TargetOpts),
213       mpModule(NULL),
214       mpOS(OS),
215       mOT(OT),
216       mGen(NULL),
217       mPerFunctionPasses(NULL),
218       mPerModulePasses(NULL),
219       mCodeGenPasses(NULL),
220       mLLVMContext(llvm::getGlobalContext()),
221       mDiagEngine(*DiagEngine),
222       mCodeGenOpts(CodeGenOpts),
223       mPragmas(Pragmas) {
224   FormattedOutStream.setStream(*mpOS,
225                                llvm::formatted_raw_ostream::PRESERVE_STREAM);
226   mGen = CreateLLVMCodeGen(mDiagEngine, "", mCodeGenOpts,
227                            mTargetOpts, mLLVMContext);
228   return;
229 }
230 
Initialize(clang::ASTContext & Ctx)231 void Backend::Initialize(clang::ASTContext &Ctx) {
232   mGen->Initialize(Ctx);
233 
234   mpModule = mGen->GetModule();
235 
236   return;
237 }
238 
239 // Encase the Bitcode in a wrapper containing RS version information.
WrapBitcode(llvm::raw_string_ostream & Bitcode)240 void Backend::WrapBitcode(llvm::raw_string_ostream &Bitcode) {
241   bcinfo::AndroidBitcodeWrapper wrapper;
242   size_t actualWrapperLen = bcinfo::writeAndroidBitcodeWrapper(
243       &wrapper, Bitcode.str().length(), getTargetAPI(),
244       SlangVersion::CURRENT, mCodeGenOpts.OptimizationLevel);
245 
246   slangAssert(actualWrapperLen > 0);
247 
248   // Write out the bitcode wrapper.
249   FormattedOutStream.write(reinterpret_cast<char*>(&wrapper), actualWrapperLen);
250 
251   // Write out the actual encoded bitcode.
252   FormattedOutStream << Bitcode.str();
253   return;
254 }
255 
HandleTopLevelDecl(clang::DeclGroupRef D)256 bool Backend::HandleTopLevelDecl(clang::DeclGroupRef D) {
257   return mGen->HandleTopLevelDecl(D);
258 }
259 
HandleTranslationUnit(clang::ASTContext & Ctx)260 void Backend::HandleTranslationUnit(clang::ASTContext &Ctx) {
261   HandleTranslationUnitPre(Ctx);
262 
263   mGen->HandleTranslationUnit(Ctx);
264 
265   // Here, we complete a translation unit (whole translation unit is now in LLVM
266   // IR). Now, interact with LLVM backend to generate actual machine code (asm
267   // or machine code, whatever.)
268 
269   // Silently ignore if we weren't initialized for some reason.
270   if (!mpModule)
271     return;
272 
273   llvm::Module *M = mGen->ReleaseModule();
274   if (!M) {
275     // The module has been released by IR gen on failures, do not double free.
276     mpModule = NULL;
277     return;
278   }
279 
280   slangAssert(mpModule == M &&
281               "Unexpected module change during LLVM IR generation");
282 
283   // Insert #pragma information into metadata section of module
284   if (!mPragmas->empty()) {
285     llvm::NamedMDNode *PragmaMetadata =
286         mpModule->getOrInsertNamedMetadata(Slang::PragmaMetadataName);
287     for (PragmaList::const_iterator I = mPragmas->begin(), E = mPragmas->end();
288          I != E;
289          I++) {
290       llvm::SmallVector<llvm::Value*, 2> Pragma;
291       // Name goes first
292       Pragma.push_back(llvm::MDString::get(mLLVMContext, I->first));
293       // And then value
294       Pragma.push_back(llvm::MDString::get(mLLVMContext, I->second));
295 
296       // Create MDNode and insert into PragmaMetadata
297       PragmaMetadata->addOperand(
298           llvm::MDNode::get(mLLVMContext, Pragma));
299     }
300   }
301 
302   HandleTranslationUnitPost(mpModule);
303 
304   // Create passes for optimization and code emission
305 
306   // Create and run per-function passes
307   CreateFunctionPasses();
308   if (mPerFunctionPasses) {
309     mPerFunctionPasses->doInitialization();
310 
311     for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end();
312          I != E;
313          I++)
314       if (!I->isDeclaration())
315         mPerFunctionPasses->run(*I);
316 
317     mPerFunctionPasses->doFinalization();
318   }
319 
320   // Create and run module passes
321   CreateModulePasses();
322   if (mPerModulePasses)
323     mPerModulePasses->run(*mpModule);
324 
325   switch (mOT) {
326     case Slang::OT_Assembly:
327     case Slang::OT_Object: {
328       if (!CreateCodeGenPasses())
329         return;
330 
331       mCodeGenPasses->doInitialization();
332 
333       for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end();
334           I != E;
335           I++)
336         if (!I->isDeclaration())
337           mCodeGenPasses->run(*I);
338 
339       mCodeGenPasses->doFinalization();
340       break;
341     }
342     case Slang::OT_LLVMAssembly: {
343       llvm::PassManager *LLEmitPM = new llvm::PassManager();
344       LLEmitPM->add(llvm::createPrintModulePass(&FormattedOutStream));
345       LLEmitPM->run(*mpModule);
346       break;
347     }
348     case Slang::OT_Bitcode: {
349       llvm::PassManager *BCEmitPM = new llvm::PassManager();
350       std::string BCStr;
351       llvm::raw_string_ostream Bitcode(BCStr);
352       unsigned int TargetAPI = getTargetAPI();
353       switch (TargetAPI) {
354         case SLANG_HC_TARGET_API:
355         case SLANG_HC_MR1_TARGET_API:
356         case SLANG_HC_MR2_TARGET_API: {
357           // Pre-ICS targets must use the LLVM 2.9 BitcodeWriter
358           BCEmitPM->add(llvm_2_9::createBitcodeWriterPass(Bitcode));
359           break;
360         }
361         case SLANG_ICS_TARGET_API:
362         case SLANG_ICS_MR1_TARGET_API: {
363           // ICS targets must use the LLVM 2.9_func BitcodeWriter
364           BCEmitPM->add(llvm_2_9_func::createBitcodeWriterPass(Bitcode));
365           break;
366         }
367         default: {
368           if (TargetAPI < SLANG_MINIMUM_TARGET_API ||
369               TargetAPI > SLANG_MAXIMUM_TARGET_API) {
370             slangAssert(false && "Invalid target API value");
371           }
372           // Switch to the 3.2 BitcodeWriter by default, and don't use
373           // LLVM's included BitcodeWriter at all (for now).
374           BCEmitPM->add(llvm_3_2::createBitcodeWriterPass(Bitcode));
375           //BCEmitPM->add(llvm::createBitcodeWriterPass(Bitcode));
376           break;
377         }
378       }
379 
380       BCEmitPM->run(*mpModule);
381       WrapBitcode(Bitcode);
382       break;
383     }
384     case Slang::OT_Nothing: {
385       return;
386     }
387     default: {
388       slangAssert(false && "Unknown output type");
389     }
390   }
391 
392   FormattedOutStream.flush();
393 
394   return;
395 }
396 
HandleTagDeclDefinition(clang::TagDecl * D)397 void Backend::HandleTagDeclDefinition(clang::TagDecl *D) {
398   mGen->HandleTagDeclDefinition(D);
399   return;
400 }
401 
CompleteTentativeDefinition(clang::VarDecl * D)402 void Backend::CompleteTentativeDefinition(clang::VarDecl *D) {
403   mGen->CompleteTentativeDefinition(D);
404   return;
405 }
406 
~Backend()407 Backend::~Backend() {
408   delete mpModule;
409   delete mGen;
410   delete mPerFunctionPasses;
411   delete mPerModulePasses;
412   delete mCodeGenPasses;
413   return;
414 }
415 
416 }  // namespace slang
417