slang_backend.cpp revision c706907a8041faaa882f9bd87f1d1c1669023a62
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
63namespace slang {
64
65void Backend::CreateFunctionPasses() {
66  if (!mPerFunctionPasses) {
67    mPerFunctionPasses = new llvm::legacy::FunctionPassManager(mpModule);
68    mPerFunctionPasses->add(new llvm::DataLayoutPass());
69
70    llvm::PassManagerBuilder PMBuilder;
71    PMBuilder.OptLevel = mCodeGenOpts.OptimizationLevel;
72    PMBuilder.populateFunctionPassManager(*mPerFunctionPasses);
73  }
74}
75
76void Backend::CreateModulePasses() {
77  if (!mPerModulePasses) {
78    mPerModulePasses = new llvm::legacy::PassManager();
79    mPerModulePasses->add(new llvm::DataLayoutPass());
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
102bool 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::legacy::FunctionPassManager(mpModule);
111    mCodeGenPasses->add(new llvm::DataLayoutPass());
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 == nullptr) {
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
204Backend::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(nullptr),
213      mpOS(OS),
214      mOT(OT),
215      mGen(nullptr),
216      mPerFunctionPasses(nullptr),
217      mPerModulePasses(nullptr),
218      mCodeGenPasses(nullptr),
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, mLLVMContext);
226}
227
228void Backend::Initialize(clang::ASTContext &Ctx) {
229  mGen->Initialize(Ctx);
230
231  mpModule = mGen->GetModule();
232}
233
234// Encase the Bitcode in a wrapper containing RS version information.
235void Backend::WrapBitcode(llvm::raw_string_ostream &Bitcode) {
236  bcinfo::AndroidBitcodeWrapper wrapper;
237  size_t actualWrapperLen = bcinfo::writeAndroidBitcodeWrapper(
238      &wrapper, Bitcode.str().length(), getTargetAPI(),
239      SlangVersion::CURRENT, mCodeGenOpts.OptimizationLevel);
240
241  slangAssert(actualWrapperLen > 0);
242
243  // Write out the bitcode wrapper.
244  FormattedOutStream.write(reinterpret_cast<char*>(&wrapper), actualWrapperLen);
245
246  // Write out the actual encoded bitcode.
247  FormattedOutStream << Bitcode.str();
248}
249
250bool Backend::HandleTopLevelDecl(clang::DeclGroupRef D) {
251  return mGen->HandleTopLevelDecl(D);
252}
253
254void Backend::HandleTranslationUnit(clang::ASTContext &Ctx) {
255  HandleTranslationUnitPre(Ctx);
256
257  mGen->HandleTranslationUnit(Ctx);
258
259  // Here, we complete a translation unit (whole translation unit is now in LLVM
260  // IR). Now, interact with LLVM backend to generate actual machine code (asm
261  // or machine code, whatever.)
262
263  // Silently ignore if we weren't initialized for some reason.
264  if (!mpModule)
265    return;
266
267  llvm::Module *M = mGen->ReleaseModule();
268  if (!M) {
269    // The module has been released by IR gen on failures, do not double free.
270    mpModule = nullptr;
271    return;
272  }
273
274  slangAssert(mpModule == M &&
275              "Unexpected module change during LLVM IR generation");
276
277  // Insert #pragma information into metadata section of module
278  if (!mPragmas->empty()) {
279    llvm::NamedMDNode *PragmaMetadata =
280        mpModule->getOrInsertNamedMetadata(Slang::PragmaMetadataName);
281    for (PragmaList::const_iterator I = mPragmas->begin(), E = mPragmas->end();
282         I != E;
283         I++) {
284      llvm::SmallVector<llvm::Metadata*, 2> Pragma;
285      // Name goes first
286      Pragma.push_back(llvm::MDString::get(mLLVMContext, I->first));
287      // And then value
288      Pragma.push_back(llvm::MDString::get(mLLVMContext, I->second));
289
290      // Create MDNode and insert into PragmaMetadata
291      PragmaMetadata->addOperand(
292          llvm::MDNode::get(mLLVMContext, Pragma));
293    }
294  }
295
296  HandleTranslationUnitPost(mpModule);
297
298  // Create passes for optimization and code emission
299
300  // Create and run per-function passes
301  CreateFunctionPasses();
302  if (mPerFunctionPasses) {
303    mPerFunctionPasses->doInitialization();
304
305    for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end();
306         I != E;
307         I++)
308      if (!I->isDeclaration())
309        mPerFunctionPasses->run(*I);
310
311    mPerFunctionPasses->doFinalization();
312  }
313
314  // Create and run module passes
315  CreateModulePasses();
316  if (mPerModulePasses)
317    mPerModulePasses->run(*mpModule);
318
319  switch (mOT) {
320    case Slang::OT_Assembly:
321    case Slang::OT_Object: {
322      if (!CreateCodeGenPasses())
323        return;
324
325      mCodeGenPasses->doInitialization();
326
327      for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end();
328          I != E;
329          I++)
330        if (!I->isDeclaration())
331          mCodeGenPasses->run(*I);
332
333      mCodeGenPasses->doFinalization();
334      break;
335    }
336    case Slang::OT_LLVMAssembly: {
337      llvm::legacy::PassManager *LLEmitPM = new llvm::legacy::PassManager();
338      LLEmitPM->add(llvm::createPrintModulePass(FormattedOutStream));
339      LLEmitPM->run(*mpModule);
340      break;
341    }
342    case Slang::OT_Bitcode: {
343      llvm::legacy::PassManager *BCEmitPM = new llvm::legacy::PassManager();
344      std::string BCStr;
345      llvm::raw_string_ostream Bitcode(BCStr);
346      unsigned int TargetAPI = getTargetAPI();
347      switch (TargetAPI) {
348        case SLANG_HC_TARGET_API:
349        case SLANG_HC_MR1_TARGET_API:
350        case SLANG_HC_MR2_TARGET_API: {
351          // Pre-ICS targets must use the LLVM 2.9 BitcodeWriter
352          BCEmitPM->add(llvm_2_9::createBitcodeWriterPass(Bitcode));
353          break;
354        }
355        case SLANG_ICS_TARGET_API:
356        case SLANG_ICS_MR1_TARGET_API: {
357          // ICS targets must use the LLVM 2.9_func BitcodeWriter
358          BCEmitPM->add(llvm_2_9_func::createBitcodeWriterPass(Bitcode));
359          break;
360        }
361        default: {
362          if (TargetAPI != SLANG_DEVELOPMENT_TARGET_API &&
363              (TargetAPI < SLANG_MINIMUM_TARGET_API ||
364               TargetAPI > SLANG_MAXIMUM_TARGET_API)) {
365            slangAssert(false && "Invalid target API value");
366          }
367          // Switch to the 3.2 BitcodeWriter by default, and don't use
368          // LLVM's included BitcodeWriter at all (for now).
369          BCEmitPM->add(llvm_3_2::createBitcodeWriterPass(Bitcode));
370          //BCEmitPM->add(llvm::createBitcodeWriterPass(Bitcode));
371          break;
372        }
373      }
374
375      BCEmitPM->run(*mpModule);
376      WrapBitcode(Bitcode);
377      break;
378    }
379    case Slang::OT_Nothing: {
380      return;
381    }
382    default: {
383      slangAssert(false && "Unknown output type");
384    }
385  }
386
387  FormattedOutStream.flush();
388}
389
390void Backend::HandleTagDeclDefinition(clang::TagDecl *D) {
391  mGen->HandleTagDeclDefinition(D);
392}
393
394void Backend::CompleteTentativeDefinition(clang::VarDecl *D) {
395  mGen->CompleteTentativeDefinition(D);
396}
397
398Backend::~Backend() {
399  delete mpModule;
400  delete mGen;
401  delete mPerFunctionPasses;
402  delete mPerModulePasses;
403  delete mCodeGenPasses;
404}
405
406}  // namespace slang
407