blob: 7554569ab183aed8e25e6a483da23d1d1a014003 [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
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070019#include "llvm/Module.h"
20#include "llvm/Metadata.h"
21#include "llvm/LLVMContext.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070022
Zonr Chang41ebf532010-10-13 18:29:18 +080023#include "llvm/Target/TargetData.h"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070024#include "llvm/Target/TargetMachine.h"
25#include "llvm/Target/TargetOptions.h"
26#include "llvm/Target/TargetRegistry.h"
27#include "llvm/Target/SubtargetFeature.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070028
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070029#include "llvm/CodeGen/RegAllocRegistry.h"
30#include "llvm/CodeGen/SchedulerRegistry.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070031
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070032#include "llvm/Assembly/PrintModulePass.h"
33#include "llvm/Bitcode/ReaderWriter.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070034
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070035#include "clang/AST/Decl.h"
36#include "clang/AST/DeclGroup.h"
37#include "clang/AST/ASTContext.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070038
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070039#include "clang/Basic/TargetInfo.h"
40#include "clang/Basic/Diagnostic.h"
41#include "clang/Basic/TargetOptions.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070042
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080043#include "clang/Frontend/CodeGenOptions.h"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070044#include "clang/Frontend/FrontendDiagnostic.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070045
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070046#include "clang/CodeGen/ModuleBuilder.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070047
zonr6315f762010-10-05 15:35:14 +080048#include "slang.h"
49
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070050using namespace slang;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070051
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080052void Backend::CreateFunctionPasses() {
53 if (!mPerFunctionPasses) {
54 mPerFunctionPasses = new llvm::FunctionPassManager(mpModule);
Zonr Chang41ebf532010-10-13 18:29:18 +080055 mPerFunctionPasses->add(new llvm::TargetData(mpModule));
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080056
57 llvm::createStandardFunctionPasses(mPerFunctionPasses,
58 mCodeGenOpts.OptimizationLevel);
59 }
60 return;
61}
62
63void Backend::CreateModulePasses() {
64 if (!mPerModulePasses) {
65 mPerModulePasses = new llvm::PassManager();
Zonr Chang41ebf532010-10-13 18:29:18 +080066 mPerModulePasses->add(new llvm::TargetData(mpModule));
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080067
68 llvm::createStandardModulePasses(mPerModulePasses,
69 mCodeGenOpts.OptimizationLevel,
70 mCodeGenOpts.OptimizeSize,
71 mCodeGenOpts.UnitAtATime,
72 mCodeGenOpts.UnrollLoops,
73 /* SimplifyLibCalls = */true,
74 /* HaveExceptions = */false,
75 /* InliningPass = */NULL);
76 }
77 return;
78}
79
Shih-wei Liao462aefd2010-06-04 15:32:04 -070080bool Backend::CreateCodeGenPasses() {
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080081 if ((mOT != Slang::OT_Assembly) && (mOT != Slang::OT_Object))
Shih-wei Liao462aefd2010-06-04 15:32:04 -070082 return true;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070083
84 // Now we add passes for code emitting
85 if (mCodeGenPasses) {
86 return true;
87 } else {
88 mCodeGenPasses = new llvm::FunctionPassManager(mpModule);
Zonr Chang41ebf532010-10-13 18:29:18 +080089 mCodeGenPasses->add(new llvm::TargetData(mpModule));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070090 }
91
92 // Create the TargetMachine for generating code.
93 std::string Triple = mpModule->getTargetTriple();
94
95 std::string Error;
96 const llvm::Target* TargetInfo =
97 llvm::TargetRegistry::lookupTarget(Triple, Error);
zonr6315f762010-10-05 15:35:14 +080098 if (TargetInfo == NULL) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070099 mDiags.Report(clang::diag::err_fe_unable_to_create_target) << Error;
100 return false;
101 }
102
103 llvm::NoFramePointerElim = mCodeGenOpts.DisableFPElim;
104
105 // Use hardware FPU.
106 //
107 // FIXME: Need to detect the CPU capability and decide whether to use softfp.
108 // To use softfp, change following 2 lines to
109 //
110 // llvm::FloatABIType = llvm::FloatABI::Soft;
111 // llvm::UseSoftFloat = true;
112 llvm::FloatABIType = llvm::FloatABI::Hard;
113 llvm::UseSoftFloat = false;
114
115 // BCC needs all unknown symbols resolved at compilation time. So we don't
116 // need any relocation model.
117 llvm::TargetMachine::setRelocationModel(llvm::Reloc::Static);
118
119
Zonr Chang41ebf532010-10-13 18:29:18 +0800120 // This is set for the linker (specify how large of the virtual addresses we
121 // can access for all unknown symbols.)
122 if (mpModule->getPointerSize() == llvm::Module::Pointer32)
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700123 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Small);
Zonr Chang41ebf532010-10-13 18:29:18 +0800124 else
125 // The target may have pointer size greater than 32 (e.g. x86_64
126 // architecture) may need large data address model
127 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Medium);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700128
129 // Setup feature string
130 std::string FeaturesStr;
131 if (mTargetOpts.CPU.size() || mTargetOpts.Features.size()) {
132 llvm::SubtargetFeatures Features;
133
134 Features.setCPU(mTargetOpts.CPU);
135
136 for (std::vector<std::string>::const_iterator
137 I = mTargetOpts.Features.begin(), E = mTargetOpts.Features.end();
138 I != E;
139 I++)
140 Features.AddFeature(*I);
141
142 FeaturesStr = Features.getString();
143 }
144 llvm::TargetMachine *TM =
145 TargetInfo->createTargetMachine(Triple, FeaturesStr);
146
147 // Register scheduler
148 llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
149
150 // Register allocation policy:
151 // createFastRegisterAllocator: fast but bad quality
152 // createLinearScanRegisterAllocator: not so fast but good quality
153 llvm::RegisterRegAlloc::setDefault((mCodeGenOpts.OptimizationLevel == 0) ?
154 llvm::createFastRegisterAllocator :
155 llvm::createLinearScanRegisterAllocator);
156
157 llvm::CodeGenOpt::Level OptLevel = llvm::CodeGenOpt::Default;
158 if (mCodeGenOpts.OptimizationLevel == 0)
159 OptLevel = llvm::CodeGenOpt::None;
160 else if (mCodeGenOpts.OptimizationLevel == 3)
161 OptLevel = llvm::CodeGenOpt::Aggressive;
162
163 llvm::TargetMachine::CodeGenFileType CGFT =
zonr6315f762010-10-05 15:35:14 +0800164 llvm::TargetMachine::CGFT_AssemblyFile;
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800165 if (mOT == Slang::OT_Object)
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700166 CGFT = llvm::TargetMachine::CGFT_ObjectFile;
167 if (TM->addPassesToEmitFile(*mCodeGenPasses, FormattedOutStream,
168 CGFT, OptLevel)) {
169 mDiags.Report(clang::diag::err_fe_unable_to_interface_with_target);
170 return false;
171 }
172
173 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700174}
175
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700176Backend::Backend(clang::Diagnostic &Diags,
177 const clang::CodeGenOptions &CodeGenOpts,
178 const clang::TargetOptions &TargetOpts,
179 const PragmaList &Pragmas,
180 llvm::raw_ostream *OS,
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800181 Slang::OutputType OT)
zonr6315f762010-10-05 15:35:14 +0800182 : ASTConsumer(),
183 mCodeGenOpts(CodeGenOpts),
184 mTargetOpts(TargetOpts),
Zonr Chang68fc02c2010-10-13 19:09:19 +0800185 mpModule(NULL),
zonr6315f762010-10-05 15:35:14 +0800186 mpOS(OS),
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800187 mOT(OT),
zonr6315f762010-10-05 15:35:14 +0800188 mGen(NULL),
189 mPerFunctionPasses(NULL),
190 mPerModulePasses(NULL),
191 mCodeGenPasses(NULL),
zonr6315f762010-10-05 15:35:14 +0800192 mLLVMContext(llvm::getGlobalContext()),
193 mDiags(Diags),
zonr6315f762010-10-05 15:35:14 +0800194 mPragmas(Pragmas) {
195 FormattedOutStream.setStream(*mpOS,
196 llvm::formatted_raw_ostream::PRESERVE_STREAM);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700197 mGen = CreateLLVMCodeGen(mDiags, "", mCodeGenOpts, mLLVMContext);
198 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700199}
200
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700201void Backend::Initialize(clang::ASTContext &Ctx) {
202 mGen->Initialize(Ctx);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700203
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700204 mpModule = mGen->GetModule();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700205
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700206 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700207}
208
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700209void Backend::HandleTopLevelDecl(clang::DeclGroupRef D) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700210 mGen->HandleTopLevelDecl(D);
211 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700212}
213
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700214void Backend::HandleTranslationUnit(clang::ASTContext &Ctx) {
Zonr Chang68fc02c2010-10-13 19:09:19 +0800215 HandleTranslationUnitPre(Ctx);
216
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700217 mGen->HandleTranslationUnit(Ctx);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700218
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700219 // Here, we complete a translation unit (whole translation unit is now in LLVM
220 // IR). Now, interact with LLVM backend to generate actual machine code (asm
221 // or machine code, whatever.)
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700222
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700223 // Silently ignore if we weren't initialized for some reason.
Zonr Chang41ebf532010-10-13 18:29:18 +0800224 if (!mpModule)
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700225 return;
226
227 llvm::Module *M = mGen->ReleaseModule();
228 if (!M) {
229 // The module has been released by IR gen on failures, do not double free.
230 mpModule = NULL;
231 return;
232 }
233
234 assert(mpModule == M && "Unexpected module change during LLVM IR generation");
235
236 // Insert #pragma information into metadata section of module
237 if (!mPragmas.empty()) {
238 llvm::NamedMDNode *PragmaMetadata =
239 mpModule->getOrInsertNamedMetadata(Slang::PragmaMetadataName);
240 for (PragmaList::const_iterator I = mPragmas.begin(), E = mPragmas.end();
241 I != E;
242 I++) {
243 llvm::SmallVector<llvm::Value*, 2> Pragma;
244 // Name goes first
245 Pragma.push_back(llvm::MDString::get(mLLVMContext, I->first));
246 // And then value
247 Pragma.push_back(llvm::MDString::get(mLLVMContext, I->second));
248 // Create MDNode and insert into PragmaMetadata
249 PragmaMetadata->addOperand(
250 llvm::MDNode::get(mLLVMContext, Pragma.data(), Pragma.size()));
251 }
252 }
253
Zonr Chang68fc02c2010-10-13 19:09:19 +0800254 HandleTranslationUnitPost(mpModule);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700255
256 // Create passes for optimization and code emission
257
258 // Create and run per-function passes
259 CreateFunctionPasses();
260 if (mPerFunctionPasses) {
261 mPerFunctionPasses->doInitialization();
262
263 for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end();
264 I != E;
265 I++)
266 if (!I->isDeclaration())
267 mPerFunctionPasses->run(*I);
268
269 mPerFunctionPasses->doFinalization();
270 }
271
272 // Create and run module passes
273 CreateModulePasses();
274 if (mPerModulePasses)
275 mPerModulePasses->run(*mpModule);
276
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800277 switch (mOT) {
278 case Slang::OT_Assembly:
279 case Slang::OT_Object: {
zonr6315f762010-10-05 15:35:14 +0800280 if (!CreateCodeGenPasses())
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700281 return;
282
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700283 mCodeGenPasses->doInitialization();
284
285 for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end();
286 I != E;
287 I++)
zonr6315f762010-10-05 15:35:14 +0800288 if (!I->isDeclaration())
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700289 mCodeGenPasses->run(*I);
290
291 mCodeGenPasses->doFinalization();
292 break;
293 }
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800294 case Slang::OT_LLVMAssembly: {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700295 llvm::PassManager *LLEmitPM = new llvm::PassManager();
296 LLEmitPM->add(llvm::createPrintModulePass(&FormattedOutStream));
297 LLEmitPM->run(*mpModule);
298 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700299 }
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800300 case Slang::OT_Bitcode: {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700301 llvm::PassManager *BCEmitPM = new llvm::PassManager();
302 BCEmitPM->add(llvm::createBitcodeWriterPass(FormattedOutStream));
303 BCEmitPM->run(*mpModule);
304 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700305 }
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800306 case Slang::OT_Nothing: {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700307 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700308 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700309 default: {
310 assert(false && "Unknown output type");
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700311 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700312 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700313
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700314 FormattedOutStream.flush();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700315
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700316 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700317}
318
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700319void Backend::HandleTagDeclDefinition(clang::TagDecl *D) {
320 mGen->HandleTagDeclDefinition(D);
321 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700322}
323
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700324void Backend::CompleteTentativeDefinition(clang::VarDecl *D) {
325 mGen->CompleteTentativeDefinition(D);
326 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700327}
328
329Backend::~Backend() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700330 delete mpModule;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700331 delete mGen;
332 delete mPerFunctionPasses;
333 delete mPerModulePasses;
334 delete mCodeGenPasses;
335 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700336}