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