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