Backend.cpp revision 05be040fdd9fa9d23259d6b6a4aaf4f2aca9c9f2
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/Support/Casting.h" 33#include "llvm/Support/InstIterator.h" 34 35#include "llvm/Target/TargetData.h" 36#include "llvm/Target/TargetMachine.h" 37#include "llvm/Target/TargetOptions.h" 38#include "llvm/Target/TargetRegistry.h" 39#include "llvm/Target/SubtargetFeature.h" 40 41namespace ndkpc { 42 43void Backend::CreateFunctionPasses() { 44 if (!mpPerFunctionPasses) { 45 mpPerFunctionPasses = new llvm::FunctionPassManager(mpModule); 46 mpPerFunctionPasses->add(new llvm::TargetData(mpModule)); 47 48 // FIXME REMOVE 49 //llvm::createStandardFunctionPasses(mpPerFunctionPasses, 50 // mCodeGenOpts.OptimizationLevel); 51 llvm::PassManagerBuilder PMBuilder; 52 PMBuilder.OptLevel = mCodeGenOpts.OptimizationLevel; 53 PMBuilder.populateFunctionPassManager(*mpPerFunctionPasses); 54 } 55 return; 56} 57 58void Backend::CreateModulePasses() { 59 if (!mpPerModulePasses) { 60 mpPerModulePasses = new llvm::PassManager(); 61 mpPerModulePasses->add(new llvm::TargetData(mpModule)); 62 63 llvm::PassManagerBuilder PMBuilder; 64 PMBuilder.OptLevel = mCodeGenOpts.OptimizationLevel; 65 PMBuilder.SizeLevel = mCodeGenOpts.OptimizeSize; 66 if (mCodeGenOpts.UnitAtATime) { 67 PMBuilder.DisableUnitAtATime = 0; 68 } else { 69 PMBuilder.DisableUnitAtATime = 1; 70 } 71 72 if (mCodeGenOpts.UnrollLoops) { 73 PMBuilder.DisableUnrollLoops = 0; 74 } else { 75 PMBuilder.DisableUnrollLoops = 1; 76 } 77 78 PMBuilder.DisableSimplifyLibCalls = false; 79 PMBuilder.populateModulePassManager(*mpPerModulePasses); 80 } 81 return; 82} 83 84bool Backend::CreateCodeGenPasses() { 85 if ((mOT != Compiler::OT_Assembly) && (mOT != Compiler::OT_Object)) 86 return true; 87 88 // Now we add passes for code emitting 89 if (mpCodeGenPasses) { 90 return true; 91 } else { 92 mpCodeGenPasses = new llvm::FunctionPassManager(mpModule); 93 mpCodeGenPasses->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 == Compiler::OT_Object) 170 CGFT = llvm::TargetMachine::CGFT_ObjectFile; 171 if (TM->addPassesToEmitFile(*mpCodeGenPasses, 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(const clang::CodeGenOptions &CodeGenOpts, 181 const clang::TargetOptions &TargetOpts, 182 clang::Diagnostic *Diags, 183 llvm::raw_ostream *OS, 184 Compiler::OutputType OT) 185 : ASTConsumer(), 186 mCodeGenOpts(CodeGenOpts), 187 mTargetOpts(TargetOpts), 188 mLLVMContext(llvm::getGlobalContext()), 189 mDiags(*Diags), 190 mpModule(NULL), 191 mpOS(OS), 192 mOT(OT), 193 mpGen(NULL), 194 mpPerFunctionPasses(NULL), 195 mpPerModulePasses(NULL), 196 mpCodeGenPasses(NULL) { 197 FormattedOutStream.setStream(*mpOS, 198 llvm::formatted_raw_ostream::PRESERVE_STREAM); 199 mpGen = CreateLLVMCodeGen(mDiags, "", mCodeGenOpts, mLLVMContext); 200 return; 201} 202 203void Backend::Initialize(clang::ASTContext &Ctx) { 204 mpGen->Initialize(Ctx); 205 mpModule = mpGen->GetModule(); 206 return; 207} 208 209void Backend::HandleTopLevelDecl(clang::DeclGroupRef D) { 210 mpGen->HandleTopLevelDecl(D); 211 return; 212} 213 214void Backend::HandleTranslationUnit(clang::ASTContext &Ctx) { 215 mpGen->HandleTranslationUnit(Ctx); 216 217 // Here, we complete a translation unit (whole translation unit is now in LLVM 218 // IR). Now, interact with LLVM backend to generate actual machine code (asm 219 // or machine code, whatever.) 220 221 // Silently ignore if we weren't initialized for some reason. 222 if (!mpModule) 223 return; 224 225 llvm::Module *M = mpGen->ReleaseModule(); 226 if (!M) { 227 // The module has been released by IR gen on failures, do not double free. 228 mpModule = NULL; 229 return; 230 } 231 232 assert(mpModule == M && 233 "Unexpected module change during LLVM IR generation"); 234 235 // Handle illigal CallSite 236 for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end(); 237 I != E; 238 ++I) { 239 for (llvm::inst_iterator i = llvm::inst_begin(*I), e = llvm::inst_end(*I); 240 i != e; 241 ++i) { 242 if (llvm::CallInst* CallInst = llvm::dyn_cast<llvm::CallInst>(&*i)) { 243 if (CallInst->isInlineAsm()) { 244 // TODO: Should we reflect source location information to diagnostic 245 // class and show to users? 246 llvm::errs() << "Inline assembly is illigal. Please don't use it." << "\n"; 247 exit(1); 248 } 249 } 250 } 251 } 252 253 // Create and run per-function passes 254 CreateFunctionPasses(); 255 if (mpPerFunctionPasses) { 256 mpPerFunctionPasses->doInitialization(); 257 258 for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end(); 259 I != E; 260 I++) 261 if (!I->isDeclaration()) 262 mpPerFunctionPasses->run(*I); 263 264 mpPerFunctionPasses->doFinalization(); 265 } 266 267 // Create and run module passes 268 CreateModulePasses(); 269 if (mpPerModulePasses) 270 mpPerModulePasses->run(*mpModule); 271 272 switch (mOT) { 273 case Compiler::OT_Assembly: 274 case Compiler::OT_Object: { 275 if (!CreateCodeGenPasses()) 276 return; 277 278 mpCodeGenPasses->doInitialization(); 279 280 for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end(); 281 I != E; 282 I++) 283 if (!I->isDeclaration()) 284 mpCodeGenPasses->run(*I); 285 286 mpCodeGenPasses->doFinalization(); 287 break; 288 } 289 case Compiler::OT_LLVMAssembly: { 290 llvm::PassManager *LLEmitPM = new llvm::PassManager(); 291 LLEmitPM->add(llvm::createPrintModulePass(&FormattedOutStream)); 292 LLEmitPM->run(*mpModule); 293 break; 294 } 295 case Compiler::OT_Bitcode: { 296 llvm::PassManager *BCEmitPM = new llvm::PassManager(); 297 BCEmitPM->add(llvm::createBitcodeWriterPass(FormattedOutStream)); 298 BCEmitPM->run(*mpModule); 299 break; 300 } 301 case Compiler::OT_Nothing: { 302 return; 303 } 304 default: { 305 assert(false && "Unknown output type"); 306 } 307 } 308 309 FormattedOutStream.flush(); 310 return; 311} 312 313void Backend::HandleTagDeclDefinition(clang::TagDecl *D) { 314 mpGen->HandleTagDeclDefinition(D); 315 return; 316} 317 318void Backend::CompleteTentativeDefinition(clang::VarDecl *D) { 319 mpGen->CompleteTentativeDefinition(D); 320 return; 321} 322 323Backend::~Backend() { 324 delete mpModule; 325 delete mpGen; 326 delete mpPerFunctionPasses; 327 delete mpPerModulePasses; 328 delete mpCodeGenPasses; 329 return; 330} 331 332} 333