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