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/MC/SubtargetFeature.h" 33 34#include "llvm/Support/Casting.h" 35#include "llvm/Support/InstIterator.h" 36 37#include "llvm/Target/TargetData.h" 38#include "llvm/Target/TargetMachine.h" 39#include "llvm/Target/TargetOptions.h" 40#include "llvm/Support/TargetRegistry.h" 41 42namespace ndkpc { 43 44void Backend::CreateFunctionPasses() { 45 if (!mpPerFunctionPasses) { 46 mpPerFunctionPasses = new llvm::FunctionPassManager(mpModule); 47 mpPerFunctionPasses->add(new llvm::TargetData(mpModule)); 48 49 // FIXME REMOVE 50 //llvm::createStandardFunctionPasses(mpPerFunctionPasses, 51 // mCodeGenOpts.OptimizationLevel); 52 llvm::PassManagerBuilder PMBuilder; 53 PMBuilder.OptLevel = mCodeGenOpts.OptimizationLevel; 54 PMBuilder.populateFunctionPassManager(*mpPerFunctionPasses); 55 } 56 return; 57} 58 59void Backend::CreateModulePasses() { 60 if (!mpPerModulePasses) { 61 mpPerModulePasses = new llvm::PassManager(); 62 mpPerModulePasses->add(new llvm::TargetData(mpModule)); 63 64 llvm::PassManagerBuilder PMBuilder; 65 PMBuilder.OptLevel = mCodeGenOpts.OptimizationLevel; 66 PMBuilder.SizeLevel = mCodeGenOpts.OptimizeSize; 67 if (mCodeGenOpts.UnitAtATime) { 68 PMBuilder.DisableUnitAtATime = 0; 69 } else { 70 PMBuilder.DisableUnitAtATime = 1; 71 } 72 73 if (mCodeGenOpts.UnrollLoops) { 74 PMBuilder.DisableUnrollLoops = 0; 75 } else { 76 PMBuilder.DisableUnrollLoops = 1; 77 } 78 79 PMBuilder.DisableSimplifyLibCalls = false; 80 PMBuilder.populateModulePassManager(*mpPerModulePasses); 81 } 82 return; 83} 84 85bool Backend::CreateCodeGenPasses() { 86 if ((mOT != Compiler::OT_Assembly) && (mOT != Compiler::OT_Object)) 87 return true; 88 89 // Now we add passes for code emitting 90 if (mpCodeGenPasses) { 91 return true; 92 } else { 93 mpCodeGenPasses = new llvm::FunctionPassManager(mpModule); 94 mpCodeGenPasses->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::TargetOptions Options; 109 Options.NoFramePointerElim = mCodeGenOpts.DisableFPElim; 110 111 // Use hardware FPU. 112 // 113 // FIXME: Need to detect the CPU capability and decide whether to use softfp. 114 // To use softfp, change following 2 lines to 115 // 116 // llvm::FloatABIType = llvm::FloatABI::Soft; 117 // llvm::UseSoftFloat = true; 118 Options.FloatABIType = llvm::FloatABI::Hard; 119 Options.UseSoftFloat = false; 120 121 // BCC needs all unknown symbols resolved at compilation time. So we don't 122 // need any relocation model. 123 llvm::Reloc::Model RelocModel = llvm::Reloc::Static; 124 125 // This is set for the linker (specify how large of the virtual addresses we 126 // can access for all unknown symbols.) 127 llvm::CodeModel::Model CodeModel; 128 if (mpModule->getPointerSize() == llvm::Module::Pointer32) 129 CodeModel = llvm::CodeModel::Small; 130 else 131 // The target may have pointer size greater than 32 (e.g. x86_64 132 // architecture) may need large data address model 133 CodeModel = llvm::CodeModel::Medium; 134 135 // Setup feature string 136 std::string FeaturesStr; 137 if (mTargetOpts.CPU.size() || mTargetOpts.Features.size()) { 138 llvm::SubtargetFeatures Features; 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 // Setup optimization level 149 llvm::CodeGenOpt::Level OptLevel = llvm::CodeGenOpt::Default; 150 if (mCodeGenOpts.OptimizationLevel == 0) 151 OptLevel = llvm::CodeGenOpt::None; 152 else if (mCodeGenOpts.OptimizationLevel == 3) 153 OptLevel = llvm::CodeGenOpt::Aggressive; 154 155 llvm::TargetMachine *TM = 156 TargetInfo->createTargetMachine(Triple, mTargetOpts.CPU, FeaturesStr, 157 Options, RelocModel, CodeModel, OptLevel); 158 159 // Register scheduler 160 llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler); 161 162 // Register allocation policy: 163 // createFastRegisterAllocator: fast but bad quality 164 // createLinearScanRegisterAllocator: not so fast but good quality 165 llvm::RegisterRegAlloc::setDefault((mCodeGenOpts.OptimizationLevel == 0) ? 166 llvm::createFastRegisterAllocator : 167 llvm::createGreedyRegisterAllocator); 168 169 llvm::TargetMachine::CodeGenFileType CGFT = 170 llvm::TargetMachine::CGFT_AssemblyFile; 171 if (mOT == Compiler::OT_Object) 172 CGFT = llvm::TargetMachine::CGFT_ObjectFile; 173 if (TM->addPassesToEmitFile(*mpCodeGenPasses, FormattedOutStream, 174 CGFT, OptLevel)) { 175 mDiags.Report(clang::diag::err_fe_unable_to_interface_with_target); 176 return false; 177 } 178 179 return true; 180} 181 182Backend::Backend(const clang::CodeGenOptions &CodeGenOpts, 183 const clang::TargetOptions &TargetOpts, 184 clang::DiagnosticsEngine *Diags, 185 llvm::raw_ostream *OS, 186 Compiler::OutputType OT) 187 : ASTConsumer(), 188 mCodeGenOpts(CodeGenOpts), 189 mTargetOpts(TargetOpts), 190 mLLVMContext(llvm::getGlobalContext()), 191 mDiags(*Diags), 192 mpModule(NULL), 193 mpOS(OS), 194 mOT(OT), 195 mpGen(NULL), 196 mpPerFunctionPasses(NULL), 197 mpPerModulePasses(NULL), 198 mpCodeGenPasses(NULL) { 199 FormattedOutStream.setStream(*mpOS, 200 llvm::formatted_raw_ostream::PRESERVE_STREAM); 201 mpGen = CreateLLVMCodeGen(mDiags, "", mCodeGenOpts, mLLVMContext); 202 return; 203} 204 205void Backend::Initialize(clang::ASTContext &Ctx) { 206 mpGen->Initialize(Ctx); 207 mpModule = mpGen->GetModule(); 208 return; 209} 210 211bool Backend::HandleTopLevelDecl(clang::DeclGroupRef D) { 212 mpGen->HandleTopLevelDecl(D); 213 return true; 214} 215 216void Backend::HandleTranslationUnit(clang::ASTContext &Ctx) { 217 mpGen->HandleTranslationUnit(Ctx); 218 219 // 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.) 222 223 // Silently ignore if we weren't initialized for some reason. 224 if (!mpModule) 225 return; 226 227 llvm::Module *M = mpGen->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 && 235 "Unexpected module change during LLVM IR generation"); 236 237 // Handle illigal CallSite 238 for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end(); 239 I != E; 240 ++I) { 241 for (llvm::inst_iterator i = llvm::inst_begin(*I), e = llvm::inst_end(*I); 242 i != e; 243 ++i) { 244 if (llvm::CallInst* CallInst = llvm::dyn_cast<llvm::CallInst>(&*i)) { 245 if (CallInst->isInlineAsm()) { 246 // TODO: Should we reflect source location information to diagnostic 247 // class and show to users? 248 llvm::errs() << "Inline assembly is illigal. Please don't use it." << "\n"; 249 exit(1); 250 } 251 } 252 } 253 } 254 255 // Create and run per-function passes 256 CreateFunctionPasses(); 257 if (mpPerFunctionPasses) { 258 mpPerFunctionPasses->doInitialization(); 259 260 for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end(); 261 I != E; 262 I++) 263 if (!I->isDeclaration()) 264 mpPerFunctionPasses->run(*I); 265 266 mpPerFunctionPasses->doFinalization(); 267 } 268 269 // Create and run module passes 270 CreateModulePasses(); 271 if (mpPerModulePasses) 272 mpPerModulePasses->run(*mpModule); 273 274 switch (mOT) { 275 case Compiler::OT_Assembly: 276 case Compiler::OT_Object: { 277 if (!CreateCodeGenPasses()) 278 return; 279 280 mpCodeGenPasses->doInitialization(); 281 282 for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end(); 283 I != E; 284 I++) 285 if (!I->isDeclaration()) 286 mpCodeGenPasses->run(*I); 287 288 mpCodeGenPasses->doFinalization(); 289 break; 290 } 291 case Compiler::OT_LLVMAssembly: { 292 llvm::PassManager *LLEmitPM = new llvm::PassManager(); 293 LLEmitPM->add(llvm::createPrintModulePass(&FormattedOutStream)); 294 LLEmitPM->run(*mpModule); 295 break; 296 } 297 case Compiler::OT_Bitcode: { 298 llvm::PassManager *BCEmitPM = new llvm::PassManager(); 299 BCEmitPM->add(llvm::createBitcodeWriterPass(FormattedOutStream)); 300 BCEmitPM->run(*mpModule); 301 break; 302 } 303 case Compiler::OT_Nothing: { 304 return; 305 } 306 default: { 307 assert(false && "Unknown output type"); 308 } 309 } 310 311 FormattedOutStream.flush(); 312 return; 313} 314 315void Backend::HandleTagDeclDefinition(clang::TagDecl *D) { 316 mpGen->HandleTagDeclDefinition(D); 317 return; 318} 319 320void Backend::CompleteTentativeDefinition(clang::VarDecl *D) { 321 mpGen->CompleteTentativeDefinition(D); 322 return; 323} 324 325Backend::~Backend() { 326 delete mpModule; 327 delete mpGen; 328 delete mpPerFunctionPasses; 329 delete mpPerModulePasses; 330 delete mpCodeGenPasses; 331 return; 332} 333 334} 335