slang_backend.cpp revision 83f0c6261efc8f397fc2509e3862bc6d0eb1e1c4
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#include "slang_assert.h" 54 55namespace slang { 56 57void Backend::CreateFunctionPasses() { 58 if (!mPerFunctionPasses) { 59 mPerFunctionPasses = new llvm::FunctionPassManager(mpModule); 60 mPerFunctionPasses->add(new llvm::TargetData(mpModule)); 61 62 llvm::createStandardFunctionPasses(mPerFunctionPasses, 63 mCodeGenOpts.OptimizationLevel); 64 } 65 return; 66} 67 68void Backend::CreateModulePasses() { 69 if (!mPerModulePasses) { 70 mPerModulePasses = new llvm::PassManager(); 71 mPerModulePasses->add(new llvm::TargetData(mpModule)); 72 73 llvm::createStandardModulePasses(mPerModulePasses, 74 mCodeGenOpts.OptimizationLevel, 75 mCodeGenOpts.OptimizeSize, 76 mCodeGenOpts.UnitAtATime, 77 mCodeGenOpts.UnrollLoops, 78 /* SimplifyLibCalls = */true, 79 /* HaveExceptions = */false, 80 /* InliningPass = */NULL); 81 } 82 return; 83} 84 85bool Backend::CreateCodeGenPasses() { 86 if ((mOT != Slang::OT_Assembly) && (mOT != Slang::OT_Object)) 87 return true; 88 89 // Now we add passes for code emitting 90 if (mCodeGenPasses) { 91 return true; 92 } else { 93 mCodeGenPasses = new llvm::FunctionPassManager(mpModule); 94 mCodeGenPasses->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 Features.setCPU(mTargetOpts.CPU); 140 141 for (std::vector<std::string>::const_iterator 142 I = mTargetOpts.Features.begin(), E = mTargetOpts.Features.end(); 143 I != E; 144 I++) 145 Features.AddFeature(*I); 146 147 FeaturesStr = Features.getString(); 148 } 149 llvm::TargetMachine *TM = 150 TargetInfo->createTargetMachine(Triple, FeaturesStr); 151 152 // Register scheduler 153 llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler); 154 155 // Register allocation policy: 156 // createFastRegisterAllocator: fast but bad quality 157 // createLinearScanRegisterAllocator: not so fast but good quality 158 llvm::RegisterRegAlloc::setDefault((mCodeGenOpts.OptimizationLevel == 0) ? 159 llvm::createFastRegisterAllocator : 160 llvm::createLinearScanRegisterAllocator); 161 162 llvm::CodeGenOpt::Level OptLevel = llvm::CodeGenOpt::Default; 163 if (mCodeGenOpts.OptimizationLevel == 0) 164 OptLevel = llvm::CodeGenOpt::None; 165 else if (mCodeGenOpts.OptimizationLevel == 3) 166 OptLevel = llvm::CodeGenOpt::Aggressive; 167 168 llvm::TargetMachine::CodeGenFileType CGFT = 169 llvm::TargetMachine::CGFT_AssemblyFile; 170 if (mOT == Slang::OT_Object) 171 CGFT = llvm::TargetMachine::CGFT_ObjectFile; 172 if (TM->addPassesToEmitFile(*mCodeGenPasses, FormattedOutStream, 173 CGFT, OptLevel)) { 174 mDiags.Report(clang::diag::err_fe_unable_to_interface_with_target); 175 return false; 176 } 177 178 return true; 179} 180 181Backend::Backend(clang::Diagnostic *Diags, 182 const clang::CodeGenOptions &CodeGenOpts, 183 const clang::TargetOptions &TargetOpts, 184 PragmaList *Pragmas, 185 llvm::raw_ostream *OS, 186 Slang::OutputType OT) 187 : ASTConsumer(), 188 mCodeGenOpts(CodeGenOpts), 189 mTargetOpts(TargetOpts), 190 mpModule(NULL), 191 mpOS(OS), 192 mOT(OT), 193 mGen(NULL), 194 mPerFunctionPasses(NULL), 195 mPerModulePasses(NULL), 196 mCodeGenPasses(NULL), 197 mLLVMContext(llvm::getGlobalContext()), 198 mDiags(*Diags), 199 mPragmas(Pragmas) { 200 FormattedOutStream.setStream(*mpOS, 201 llvm::formatted_raw_ostream::PRESERVE_STREAM); 202 mGen = CreateLLVMCodeGen(mDiags, "", mCodeGenOpts, mLLVMContext); 203 return; 204} 205 206void Backend::Initialize(clang::ASTContext &Ctx) { 207 mGen->Initialize(Ctx); 208 209 mpModule = mGen->GetModule(); 210 211 return; 212} 213 214void Backend::HandleTopLevelDecl(clang::DeclGroupRef D) { 215 mGen->HandleTopLevelDecl(D); 216 return; 217} 218 219void Backend::HandleTranslationUnit(clang::ASTContext &Ctx) { 220 HandleTranslationUnitPre(Ctx); 221 222 mGen->HandleTranslationUnit(Ctx); 223 224 // Here, we complete a translation unit (whole translation unit is now in LLVM 225 // IR). Now, interact with LLVM backend to generate actual machine code (asm 226 // or machine code, whatever.) 227 228 // Silently ignore if we weren't initialized for some reason. 229 if (!mpModule) 230 return; 231 232 llvm::Module *M = mGen->ReleaseModule(); 233 if (!M) { 234 // The module has been released by IR gen on failures, do not double free. 235 mpModule = NULL; 236 return; 237 } 238 239 slangAssert(mpModule == M && 240 "Unexpected module change during LLVM IR generation"); 241 242 // Insert #pragma information into metadata section of module 243 if (!mPragmas->empty()) { 244 llvm::NamedMDNode *PragmaMetadata = 245 mpModule->getOrInsertNamedMetadata(Slang::PragmaMetadataName); 246 for (PragmaList::const_iterator I = mPragmas->begin(), E = mPragmas->end(); 247 I != E; 248 I++) { 249 llvm::SmallVector<llvm::Value*, 2> Pragma; 250 // Name goes first 251 Pragma.push_back(llvm::MDString::get(mLLVMContext, I->first)); 252 // And then value 253 Pragma.push_back(llvm::MDString::get(mLLVMContext, I->second)); 254 255 // Create MDNode and insert into PragmaMetadata 256 llvm::ArrayRef<llvm::Value*> PragmaArray(Pragma); 257 PragmaMetadata->addOperand( 258 llvm::MDNode::get(mLLVMContext, PragmaArray)); 259 } 260 } 261 262 HandleTranslationUnitPost(mpModule); 263 264 // Create passes for optimization and code emission 265 266 // Create and run per-function passes 267 CreateFunctionPasses(); 268 if (mPerFunctionPasses) { 269 mPerFunctionPasses->doInitialization(); 270 271 for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end(); 272 I != E; 273 I++) 274 if (!I->isDeclaration()) 275 mPerFunctionPasses->run(*I); 276 277 mPerFunctionPasses->doFinalization(); 278 } 279 280 // Create and run module passes 281 CreateModulePasses(); 282 if (mPerModulePasses) 283 mPerModulePasses->run(*mpModule); 284 285 switch (mOT) { 286 case Slang::OT_Assembly: 287 case Slang::OT_Object: { 288 if (!CreateCodeGenPasses()) 289 return; 290 291 mCodeGenPasses->doInitialization(); 292 293 for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end(); 294 I != E; 295 I++) 296 if (!I->isDeclaration()) 297 mCodeGenPasses->run(*I); 298 299 mCodeGenPasses->doFinalization(); 300 break; 301 } 302 case Slang::OT_LLVMAssembly: { 303 llvm::PassManager *LLEmitPM = new llvm::PassManager(); 304 LLEmitPM->add(llvm::createPrintModulePass(&FormattedOutStream)); 305 LLEmitPM->run(*mpModule); 306 break; 307 } 308 case Slang::OT_Bitcode: { 309 llvm::PassManager *BCEmitPM = new llvm::PassManager(); 310 BCEmitPM->add(llvm::createBitcodeWriterPass(FormattedOutStream)); 311 BCEmitPM->run(*mpModule); 312 break; 313 } 314 case Slang::OT_Nothing: { 315 return; 316 } 317 default: { 318 slangAssert(false && "Unknown output type"); 319 } 320 } 321 322 FormattedOutStream.flush(); 323 324 return; 325} 326 327void Backend::HandleTagDeclDefinition(clang::TagDecl *D) { 328 mGen->HandleTagDeclDefinition(D); 329 return; 330} 331 332void Backend::CompleteTentativeDefinition(clang::VarDecl *D) { 333 mGen->CompleteTentativeDefinition(D); 334 return; 335} 336 337Backend::~Backend() { 338 delete mpModule; 339 delete mGen; 340 delete mPerFunctionPasses; 341 delete mPerModulePasses; 342 delete mCodeGenPasses; 343 return; 344} 345 346} // namespace slang 347