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