blob: ca07a49d97acec39d82d48d4aef38763284d62c4 [file] [log] [blame]
Zonr Changc383a502010-10-12 01:52:08 +08001/*
2 * Copyright 2010, 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
zonr6315f762010-10-05 15:35:14 +080017#include "slang_backend.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070018
Stephen Hinese639eb52010-11-08 19:27:20 -080019#include <string>
20#include <vector>
21
22#include "clang/AST/ASTContext.h"
23#include "clang/AST/Decl.h"
24#include "clang/AST/DeclGroup.h"
25
26#include "clang/Basic/Diagnostic.h"
27#include "clang/Basic/TargetInfo.h"
28#include "clang/Basic/TargetOptions.h"
29
30#include "clang/CodeGen/ModuleBuilder.h"
31
32#include "clang/Frontend/CodeGenOptions.h"
33#include "clang/Frontend/FrontendDiagnostic.h"
34
35#include "llvm/Assembly/PrintModulePass.h"
36
37#include "llvm/Bitcode/ReaderWriter.h"
38
39#include "llvm/CodeGen/RegAllocRegistry.h"
40#include "llvm/CodeGen/SchedulerRegistry.h"
41
42#include "llvm/LLVMContext.h"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070043#include "llvm/Module.h"
44#include "llvm/Metadata.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070045
Logan Chien9207a2e2011-10-21 15:39:28 +080046#include "llvm/Transforms/IPO/PassManagerBuilder.h"
Shih-wei Liaofcc654a2011-06-22 04:47:33 -070047
Zonr Chang41ebf532010-10-13 18:29:18 +080048#include "llvm/Target/TargetData.h"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070049#include "llvm/Target/TargetMachine.h"
50#include "llvm/Target/TargetOptions.h"
Logan Chien9207a2e2011-10-21 15:39:28 +080051#include "llvm/Support/TargetRegistry.h"
Shih-wei Liao77703262011-07-02 11:30:32 -070052
53#include "llvm/MC/SubtargetFeature.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070054
Stephen Hines6e6578a2011-02-07 18:05:48 -080055#include "slang_assert.h"
Stephen Hines4cc499d2011-08-24 19:06:17 -070056#include "BitWriter_2_9/ReaderWriter_2_9.h"
zonr6315f762010-10-05 15:35:14 +080057
Stephen Hinese639eb52010-11-08 19:27:20 -080058namespace slang {
Shih-wei Liao462aefd2010-06-04 15:32:04 -070059
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080060void Backend::CreateFunctionPasses() {
61 if (!mPerFunctionPasses) {
62 mPerFunctionPasses = new llvm::FunctionPassManager(mpModule);
Zonr Chang41ebf532010-10-13 18:29:18 +080063 mPerFunctionPasses->add(new llvm::TargetData(mpModule));
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080064
Shih-wei Liaofcc654a2011-06-22 04:47:33 -070065 llvm::PassManagerBuilder PMBuilder;
66 PMBuilder.OptLevel = mCodeGenOpts.OptimizationLevel;
67 PMBuilder.populateFunctionPassManager(*mPerFunctionPasses);
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080068 }
69 return;
70}
71
72void Backend::CreateModulePasses() {
73 if (!mPerModulePasses) {
74 mPerModulePasses = new llvm::PassManager();
Zonr Chang41ebf532010-10-13 18:29:18 +080075 mPerModulePasses->add(new llvm::TargetData(mpModule));
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080076
Shih-wei Liaofcc654a2011-06-22 04:47:33 -070077 llvm::PassManagerBuilder PMBuilder;
78 PMBuilder.OptLevel = mCodeGenOpts.OptimizationLevel;
79 PMBuilder.SizeLevel = mCodeGenOpts.OptimizeSize;
80 PMBuilder.SizeLevel = mCodeGenOpts.OptimizeSize;
81 if (mCodeGenOpts.UnitAtATime) {
82 PMBuilder.DisableUnitAtATime = 0;
83 } else {
84 PMBuilder.DisableUnitAtATime = 1;
85 }
86
87 if (mCodeGenOpts.UnrollLoops) {
88 PMBuilder.DisableUnrollLoops = 0;
89 } else {
90 PMBuilder.DisableUnrollLoops = 1;
91 }
92
93 PMBuilder.DisableSimplifyLibCalls = false;
94 PMBuilder.populateModulePassManager(*mPerModulePasses);
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080095 }
96 return;
97}
98
Shih-wei Liao462aefd2010-06-04 15:32:04 -070099bool Backend::CreateCodeGenPasses() {
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800100 if ((mOT != Slang::OT_Assembly) && (mOT != Slang::OT_Object))
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700101 return true;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700102
103 // Now we add passes for code emitting
104 if (mCodeGenPasses) {
105 return true;
106 } else {
107 mCodeGenPasses = new llvm::FunctionPassManager(mpModule);
Zonr Chang41ebf532010-10-13 18:29:18 +0800108 mCodeGenPasses->add(new llvm::TargetData(mpModule));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700109 }
110
111 // Create the TargetMachine for generating code.
112 std::string Triple = mpModule->getTargetTriple();
113
114 std::string Error;
115 const llvm::Target* TargetInfo =
116 llvm::TargetRegistry::lookupTarget(Triple, Error);
zonr6315f762010-10-05 15:35:14 +0800117 if (TargetInfo == NULL) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800118 mDiagEngine.Report(clang::diag::err_fe_unable_to_create_target) << Error;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700119 return false;
120 }
121
122 llvm::NoFramePointerElim = mCodeGenOpts.DisableFPElim;
123
124 // Use hardware FPU.
125 //
126 // FIXME: Need to detect the CPU capability and decide whether to use softfp.
127 // To use softfp, change following 2 lines to
128 //
129 // llvm::FloatABIType = llvm::FloatABI::Soft;
130 // llvm::UseSoftFloat = true;
131 llvm::FloatABIType = llvm::FloatABI::Hard;
132 llvm::UseSoftFloat = false;
133
134 // BCC needs all unknown symbols resolved at compilation time. So we don't
135 // need any relocation model.
Logan Chienab992e52011-07-20 22:06:52 +0800136 llvm::Reloc::Model RM = llvm::Reloc::Static;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700137
Zonr Chang41ebf532010-10-13 18:29:18 +0800138 // This is set for the linker (specify how large of the virtual addresses we
139 // can access for all unknown symbols.)
Logan Chien9207a2e2011-10-21 15:39:28 +0800140 llvm::CodeModel::Model CM;
141 if (mpModule->getPointerSize() == llvm::Module::Pointer32) {
142 CM = llvm::CodeModel::Small;
143 } else {
Zonr Chang41ebf532010-10-13 18:29:18 +0800144 // The target may have pointer size greater than 32 (e.g. x86_64
145 // architecture) may need large data address model
Logan Chien9207a2e2011-10-21 15:39:28 +0800146 CM = llvm::CodeModel::Medium;
147 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700148
149 // Setup feature string
150 std::string FeaturesStr;
151 if (mTargetOpts.CPU.size() || mTargetOpts.Features.size()) {
152 llvm::SubtargetFeatures Features;
153
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700154 for (std::vector<std::string>::const_iterator
155 I = mTargetOpts.Features.begin(), E = mTargetOpts.Features.end();
156 I != E;
157 I++)
158 Features.AddFeature(*I);
159
160 FeaturesStr = Features.getString();
161 }
Logan Chien9207a2e2011-10-21 15:39:28 +0800162
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700163 llvm::TargetMachine *TM =
Logan Chien9207a2e2011-10-21 15:39:28 +0800164 TargetInfo->createTargetMachine(Triple, mTargetOpts.CPU, FeaturesStr,
165 RM, CM);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700166
167 // Register scheduler
168 llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
169
170 // Register allocation policy:
171 // createFastRegisterAllocator: fast but bad quality
172 // createLinearScanRegisterAllocator: not so fast but good quality
173 llvm::RegisterRegAlloc::setDefault((mCodeGenOpts.OptimizationLevel == 0) ?
174 llvm::createFastRegisterAllocator :
175 llvm::createLinearScanRegisterAllocator);
176
177 llvm::CodeGenOpt::Level OptLevel = llvm::CodeGenOpt::Default;
Shih-wei Liao77703262011-07-02 11:30:32 -0700178 if (mCodeGenOpts.OptimizationLevel == 0) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700179 OptLevel = llvm::CodeGenOpt::None;
Shih-wei Liao77703262011-07-02 11:30:32 -0700180 } else if (mCodeGenOpts.OptimizationLevel == 3) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700181 OptLevel = llvm::CodeGenOpt::Aggressive;
Shih-wei Liao77703262011-07-02 11:30:32 -0700182 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700183
184 llvm::TargetMachine::CodeGenFileType CGFT =
zonr6315f762010-10-05 15:35:14 +0800185 llvm::TargetMachine::CGFT_AssemblyFile;
Shih-wei Liao77703262011-07-02 11:30:32 -0700186 if (mOT == Slang::OT_Object) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700187 CGFT = llvm::TargetMachine::CGFT_ObjectFile;
Shih-wei Liao77703262011-07-02 11:30:32 -0700188 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700189 if (TM->addPassesToEmitFile(*mCodeGenPasses, FormattedOutStream,
190 CGFT, OptLevel)) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800191 mDiagEngine.Report(clang::diag::err_fe_unable_to_interface_with_target);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700192 return false;
193 }
194
195 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700196}
197
Logan Chien9207a2e2011-10-21 15:39:28 +0800198Backend::Backend(clang::DiagnosticsEngine *DiagEngine,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700199 const clang::CodeGenOptions &CodeGenOpts,
200 const clang::TargetOptions &TargetOpts,
Stephen Hines3fd0a942011-01-18 12:27:39 -0800201 PragmaList *Pragmas,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700202 llvm::raw_ostream *OS,
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800203 Slang::OutputType OT)
zonr6315f762010-10-05 15:35:14 +0800204 : ASTConsumer(),
205 mCodeGenOpts(CodeGenOpts),
206 mTargetOpts(TargetOpts),
Zonr Chang68fc02c2010-10-13 19:09:19 +0800207 mpModule(NULL),
zonr6315f762010-10-05 15:35:14 +0800208 mpOS(OS),
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800209 mOT(OT),
zonr6315f762010-10-05 15:35:14 +0800210 mGen(NULL),
211 mPerFunctionPasses(NULL),
212 mPerModulePasses(NULL),
213 mCodeGenPasses(NULL),
zonr6315f762010-10-05 15:35:14 +0800214 mLLVMContext(llvm::getGlobalContext()),
Logan Chien9207a2e2011-10-21 15:39:28 +0800215 mDiagEngine(*DiagEngine),
zonr6315f762010-10-05 15:35:14 +0800216 mPragmas(Pragmas) {
217 FormattedOutStream.setStream(*mpOS,
218 llvm::formatted_raw_ostream::PRESERVE_STREAM);
Logan Chien9207a2e2011-10-21 15:39:28 +0800219 mGen = CreateLLVMCodeGen(mDiagEngine, "", mCodeGenOpts, mLLVMContext);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700220 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700221}
222
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700223void Backend::Initialize(clang::ASTContext &Ctx) {
224 mGen->Initialize(Ctx);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700225
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700226 mpModule = mGen->GetModule();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700227
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700228 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700229}
230
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700231void Backend::HandleTopLevelDecl(clang::DeclGroupRef D) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700232 mGen->HandleTopLevelDecl(D);
233 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700234}
235
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700236void Backend::HandleTranslationUnit(clang::ASTContext &Ctx) {
Zonr Chang68fc02c2010-10-13 19:09:19 +0800237 HandleTranslationUnitPre(Ctx);
238
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700239 mGen->HandleTranslationUnit(Ctx);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700240
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700241 // Here, we complete a translation unit (whole translation unit is now in LLVM
242 // IR). Now, interact with LLVM backend to generate actual machine code (asm
243 // or machine code, whatever.)
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700244
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700245 // Silently ignore if we weren't initialized for some reason.
Zonr Chang41ebf532010-10-13 18:29:18 +0800246 if (!mpModule)
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700247 return;
248
249 llvm::Module *M = mGen->ReleaseModule();
250 if (!M) {
251 // The module has been released by IR gen on failures, do not double free.
252 mpModule = NULL;
253 return;
254 }
255
Stephen Hines6e6578a2011-02-07 18:05:48 -0800256 slangAssert(mpModule == M &&
257 "Unexpected module change during LLVM IR generation");
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700258
259 // Insert #pragma information into metadata section of module
Stephen Hines3fd0a942011-01-18 12:27:39 -0800260 if (!mPragmas->empty()) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700261 llvm::NamedMDNode *PragmaMetadata =
262 mpModule->getOrInsertNamedMetadata(Slang::PragmaMetadataName);
Stephen Hines3fd0a942011-01-18 12:27:39 -0800263 for (PragmaList::const_iterator I = mPragmas->begin(), E = mPragmas->end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700264 I != E;
265 I++) {
266 llvm::SmallVector<llvm::Value*, 2> Pragma;
267 // Name goes first
268 Pragma.push_back(llvm::MDString::get(mLLVMContext, I->first));
269 // And then value
270 Pragma.push_back(llvm::MDString::get(mLLVMContext, I->second));
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700271
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700272 // Create MDNode and insert into PragmaMetadata
273 PragmaMetadata->addOperand(
Stephen Hines18c88292011-07-14 22:46:15 -0700274 llvm::MDNode::get(mLLVMContext, Pragma));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700275 }
276 }
277
Zonr Chang68fc02c2010-10-13 19:09:19 +0800278 HandleTranslationUnitPost(mpModule);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700279
280 // Create passes for optimization and code emission
281
282 // Create and run per-function passes
283 CreateFunctionPasses();
284 if (mPerFunctionPasses) {
285 mPerFunctionPasses->doInitialization();
286
287 for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end();
288 I != E;
289 I++)
290 if (!I->isDeclaration())
291 mPerFunctionPasses->run(*I);
292
293 mPerFunctionPasses->doFinalization();
294 }
295
296 // Create and run module passes
297 CreateModulePasses();
298 if (mPerModulePasses)
299 mPerModulePasses->run(*mpModule);
300
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800301 switch (mOT) {
302 case Slang::OT_Assembly:
303 case Slang::OT_Object: {
zonr6315f762010-10-05 15:35:14 +0800304 if (!CreateCodeGenPasses())
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700305 return;
306
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700307 mCodeGenPasses->doInitialization();
308
309 for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end();
310 I != E;
311 I++)
zonr6315f762010-10-05 15:35:14 +0800312 if (!I->isDeclaration())
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700313 mCodeGenPasses->run(*I);
314
315 mCodeGenPasses->doFinalization();
316 break;
317 }
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800318 case Slang::OT_LLVMAssembly: {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700319 llvm::PassManager *LLEmitPM = new llvm::PassManager();
320 LLEmitPM->add(llvm::createPrintModulePass(&FormattedOutStream));
321 LLEmitPM->run(*mpModule);
322 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700323 }
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800324 case Slang::OT_Bitcode: {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700325 llvm::PassManager *BCEmitPM = new llvm::PassManager();
Stephen Hines4cc499d2011-08-24 19:06:17 -0700326 if (getTargetAPI() < SLANG_ICS_TARGET_API) {
327 // Pre-ICS targets must use the LLVM 2.9 BitcodeWriter
328 BCEmitPM->add(llvm_2_9::createBitcodeWriterPass(FormattedOutStream));
329 } else {
330 BCEmitPM->add(llvm::createBitcodeWriterPass(FormattedOutStream));
331 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700332 BCEmitPM->run(*mpModule);
333 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700334 }
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800335 case Slang::OT_Nothing: {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700336 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700337 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700338 default: {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800339 slangAssert(false && "Unknown output type");
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700340 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700341 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700342
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700343 FormattedOutStream.flush();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700344
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700345 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700346}
347
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700348void Backend::HandleTagDeclDefinition(clang::TagDecl *D) {
349 mGen->HandleTagDeclDefinition(D);
350 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700351}
352
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700353void Backend::CompleteTentativeDefinition(clang::VarDecl *D) {
354 mGen->CompleteTentativeDefinition(D);
355 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700356}
357
358Backend::~Backend() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700359 delete mpModule;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700360 delete mGen;
361 delete mPerFunctionPasses;
362 delete mPerModulePasses;
363 delete mCodeGenPasses;
364 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700365}
Stephen Hinese639eb52010-11-08 19:27:20 -0800366
367} // namespace slang