slang_backend.cpp revision 3a9ca1f0d6bd8f12c2bb2adea51f95c255996180
1#include "slang_backend.h"
2
3#include "llvm/Module.h"
4#include "llvm/Metadata.h"
5#include "llvm/LLVMContext.h"
6
7#include "llvm/Target/TargetMachine.h"
8#include "llvm/Target/TargetOptions.h"
9#include "llvm/Target/TargetRegistry.h"
10#include "llvm/Target/SubtargetFeature.h"
11
12#include "llvm/CodeGen/RegAllocRegistry.h"
13#include "llvm/CodeGen/SchedulerRegistry.h"
14
15#include "llvm/Assembly/PrintModulePass.h"
16#include "llvm/Bitcode/ReaderWriter.h"
17
18#include "clang/AST/Decl.h"
19#include "clang/AST/DeclGroup.h"
20#include "clang/AST/ASTContext.h"
21
22#include "clang/Basic/TargetInfo.h"
23#include "clang/Basic/Diagnostic.h"
24#include "clang/Basic/TargetOptions.h"
25
26#include "clang/Frontend/CodeGenOptions.h"
27#include "clang/Frontend/FrontendDiagnostic.h"
28
29#include "clang/CodeGen/ModuleBuilder.h"
30
31#include "slang.h"
32
33using namespace slang;
34
35void Backend::CreateFunctionPasses() {
36  if (!mPerFunctionPasses) {
37    mPerFunctionPasses = new llvm::FunctionPassManager(mpModule);
38    mPerFunctionPasses->add(new llvm::TargetData(*mpTargetData));
39
40    llvm::createStandardFunctionPasses(mPerFunctionPasses,
41                                       mCodeGenOpts.OptimizationLevel);
42  }
43  return;
44}
45
46void Backend::CreateModulePasses() {
47  if (!mPerModulePasses) {
48    mPerModulePasses = new llvm::PassManager();
49    mPerModulePasses->add(new llvm::TargetData(*mpTargetData));
50
51    llvm::createStandardModulePasses(mPerModulePasses,
52                                     mCodeGenOpts.OptimizationLevel,
53                                     mCodeGenOpts.OptimizeSize,
54                                     mCodeGenOpts.UnitAtATime,
55                                     mCodeGenOpts.UnrollLoops,
56                                     /* SimplifyLibCalls = */true,
57                                     /* HaveExceptions = */false,
58                                     /* InliningPass = */NULL);
59  }
60  return;
61}
62
63bool Backend::CreateCodeGenPasses() {
64  if ((mOT != Slang::OT_Assembly) && (mOT != Slang::OT_Object))
65    return true;
66
67  // Now we add passes for code emitting
68  if (mCodeGenPasses) {
69    return true;
70  } else {
71    mCodeGenPasses = new llvm::FunctionPassManager(mpModule);
72    mCodeGenPasses->add(new llvm::TargetData(*mpTargetData));
73  }
74
75  // Create the TargetMachine for generating code.
76  std::string Triple = mpModule->getTargetTriple();
77
78  std::string Error;
79  const llvm::Target* TargetInfo =
80      llvm::TargetRegistry::lookupTarget(Triple, Error);
81  if (TargetInfo == NULL) {
82    mDiags.Report(clang::diag::err_fe_unable_to_create_target) << Error;
83    return false;
84  }
85
86  llvm::NoFramePointerElim = mCodeGenOpts.DisableFPElim;
87
88  // Use hardware FPU.
89  //
90  // FIXME: Need to detect the CPU capability and decide whether to use softfp.
91  // To use softfp, change following 2 lines to
92  //
93  //  llvm::FloatABIType = llvm::FloatABI::Soft;
94  //  llvm::UseSoftFloat = true;
95  llvm::FloatABIType = llvm::FloatABI::Hard;
96  llvm::UseSoftFloat = false;
97
98  // BCC needs all unknown symbols resolved at compilation time. So we don't
99  // need any relocation model.
100  llvm::TargetMachine::setRelocationModel(llvm::Reloc::Static);
101
102
103  // The target with pointer size greater than 32 (e.g. x86_64 architecture) may
104  // need large data address model
105  if (mpTargetData->getPointerSizeInBits() > 32)
106    llvm::TargetMachine::setCodeModel(llvm::CodeModel::Medium);
107  else
108    // This is set for the linker (specify how large of the virtual addresses we
109    // can access for all unknown symbols.)
110
111    llvm::TargetMachine::setCodeModel(llvm::CodeModel::Small);
112
113  // Setup feature string
114  std::string FeaturesStr;
115  if (mTargetOpts.CPU.size() || mTargetOpts.Features.size()) {
116    llvm::SubtargetFeatures Features;
117
118    Features.setCPU(mTargetOpts.CPU);
119
120    for (std::vector<std::string>::const_iterator
121             I = mTargetOpts.Features.begin(), E = mTargetOpts.Features.end();
122         I != E;
123         I++)
124      Features.AddFeature(*I);
125
126    FeaturesStr = Features.getString();
127  }
128  llvm::TargetMachine *TM =
129      TargetInfo->createTargetMachine(Triple, FeaturesStr);
130
131  // Register scheduler
132  llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
133
134  // Register allocation policy:
135  //  createFastRegisterAllocator: fast but bad quality
136  //  createLinearScanRegisterAllocator: not so fast but good quality
137  llvm::RegisterRegAlloc::setDefault((mCodeGenOpts.OptimizationLevel == 0) ?
138                                     llvm::createFastRegisterAllocator :
139                                     llvm::createLinearScanRegisterAllocator);
140
141  llvm::CodeGenOpt::Level OptLevel = llvm::CodeGenOpt::Default;
142  if (mCodeGenOpts.OptimizationLevel == 0)
143    OptLevel = llvm::CodeGenOpt::None;
144  else if (mCodeGenOpts.OptimizationLevel == 3)
145    OptLevel = llvm::CodeGenOpt::Aggressive;
146
147  llvm::TargetMachine::CodeGenFileType CGFT =
148      llvm::TargetMachine::CGFT_AssemblyFile;
149  if (mOT == Slang::OT_Object)
150    CGFT = llvm::TargetMachine::CGFT_ObjectFile;
151  if (TM->addPassesToEmitFile(*mCodeGenPasses, FormattedOutStream,
152                              CGFT, OptLevel)) {
153    mDiags.Report(clang::diag::err_fe_unable_to_interface_with_target);
154    return false;
155  }
156
157  return true;
158}
159
160Backend::Backend(clang::Diagnostic &Diags,
161                 const clang::CodeGenOptions &CodeGenOpts,
162                 const clang::TargetOptions &TargetOpts,
163                 const PragmaList &Pragmas,
164                 llvm::raw_ostream *OS,
165                 Slang::OutputType OT)
166    : ASTConsumer(),
167      mCodeGenOpts(CodeGenOpts),
168      mTargetOpts(TargetOpts),
169      mpOS(OS),
170      mOT(OT),
171      mpTargetData(NULL),
172      mGen(NULL),
173      mPerFunctionPasses(NULL),
174      mPerModulePasses(NULL),
175      mCodeGenPasses(NULL),
176      mLLVMContext(llvm::getGlobalContext()),
177      mDiags(Diags),
178      mpModule(NULL),
179      mPragmas(Pragmas) {
180  FormattedOutStream.setStream(*mpOS,
181                               llvm::formatted_raw_ostream::PRESERVE_STREAM);
182  mGen = CreateLLVMCodeGen(mDiags, "", mCodeGenOpts, mLLVMContext);
183  return;
184}
185
186void Backend::Initialize(clang::ASTContext &Ctx) {
187  mGen->Initialize(Ctx);
188
189  mpModule = mGen->GetModule();
190  mpTargetData = new llvm::TargetData(Slang::TargetDescription);
191
192  return;
193}
194
195void Backend::HandleTopLevelDecl(clang::DeclGroupRef D) {
196  mGen->HandleTopLevelDecl(D);
197  return;
198}
199
200void Backend::HandleTranslationUnit(clang::ASTContext &Ctx) {
201  mGen->HandleTranslationUnit(Ctx);
202
203  // Here, we complete a translation unit (whole translation unit is now in LLVM
204  // IR). Now, interact with LLVM backend to generate actual machine code (asm
205  // or machine code, whatever.)
206
207  // Silently ignore if we weren't initialized for some reason.
208  if (!mpModule || !mpTargetData)
209    return;
210
211  llvm::Module *M = mGen->ReleaseModule();
212  if (!M) {
213    // The module has been released by IR gen on failures, do not double free.
214    mpModule = NULL;
215    return;
216  }
217
218  assert(mpModule == M && "Unexpected module change during LLVM IR generation");
219
220  // Insert #pragma information into metadata section of module
221  if (!mPragmas.empty()) {
222    llvm::NamedMDNode *PragmaMetadata =
223        mpModule->getOrInsertNamedMetadata(Slang::PragmaMetadataName);
224    for (PragmaList::const_iterator I = mPragmas.begin(), E = mPragmas.end();
225         I != E;
226         I++) {
227      llvm::SmallVector<llvm::Value*, 2> Pragma;
228      // Name goes first
229      Pragma.push_back(llvm::MDString::get(mLLVMContext, I->first));
230      // And then value
231      Pragma.push_back(llvm::MDString::get(mLLVMContext, I->second));
232      // Create MDNode and insert into PragmaMetadata
233      PragmaMetadata->addOperand(
234          llvm::MDNode::get(mLLVMContext, Pragma.data(), Pragma.size()));
235    }
236  }
237
238  HandleTranslationUnitEx(Ctx);
239
240  // Create passes for optimization and code emission
241
242  // Create and run per-function passes
243  CreateFunctionPasses();
244  if (mPerFunctionPasses) {
245    mPerFunctionPasses->doInitialization();
246
247    for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end();
248         I != E;
249         I++)
250      if (!I->isDeclaration())
251        mPerFunctionPasses->run(*I);
252
253    mPerFunctionPasses->doFinalization();
254  }
255
256  // Create and run module passes
257  CreateModulePasses();
258  if (mPerModulePasses)
259    mPerModulePasses->run(*mpModule);
260
261  switch (mOT) {
262    case Slang::OT_Assembly:
263    case Slang::OT_Object: {
264      if (!CreateCodeGenPasses())
265        return;
266
267      mCodeGenPasses->doInitialization();
268
269      for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end();
270          I != E;
271          I++)
272        if (!I->isDeclaration())
273          mCodeGenPasses->run(*I);
274
275      mCodeGenPasses->doFinalization();
276      break;
277    }
278    case Slang::OT_LLVMAssembly: {
279      llvm::PassManager *LLEmitPM = new llvm::PassManager();
280      LLEmitPM->add(llvm::createPrintModulePass(&FormattedOutStream));
281      LLEmitPM->run(*mpModule);
282      break;
283    }
284    case Slang::OT_Bitcode: {
285      llvm::PassManager *BCEmitPM = new llvm::PassManager();
286      BCEmitPM->add(llvm::createBitcodeWriterPass(FormattedOutStream));
287      BCEmitPM->run(*mpModule);
288      break;
289    }
290    case Slang::OT_Nothing: {
291      return;
292    }
293    default: {
294      assert(false && "Unknown output type");
295    }
296  }
297
298  FormattedOutStream.flush();
299
300  return;
301}
302
303void Backend::HandleTagDeclDefinition(clang::TagDecl *D) {
304  mGen->HandleTagDeclDefinition(D);
305  return;
306}
307
308void Backend::CompleteTentativeDefinition(clang::VarDecl *D) {
309  mGen->CompleteTentativeDefinition(D);
310  return;
311}
312
313Backend::~Backend() {
314  delete mpModule;
315  delete mpTargetData;
316  delete mGen;
317  delete mPerFunctionPasses;
318  delete mPerModulePasses;
319  delete mCodeGenPasses;
320  return;
321}
322