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