slang_backend.cpp revision c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9
1/* 2 * Copyright 2010-2012, 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/ADT/Twine.h" 36#include "llvm/ADT/StringExtras.h" 37 38#include "llvm/Bitcode/ReaderWriter.h" 39 40#include "llvm/CodeGen/RegAllocRegistry.h" 41#include "llvm/CodeGen/SchedulerRegistry.h" 42 43#include "llvm/IR/Constant.h" 44#include "llvm/IR/Constants.h" 45#include "llvm/IR/DataLayout.h" 46#include "llvm/IR/DebugLoc.h" 47#include "llvm/IR/DerivedTypes.h" 48#include "llvm/IR/Function.h" 49#include "llvm/IR/IRBuilder.h" 50#include "llvm/IR/IRPrintingPasses.h" 51#include "llvm/IR/LLVMContext.h" 52#include "llvm/IR/Metadata.h" 53#include "llvm/IR/Module.h" 54 55#include "llvm/Transforms/IPO/PassManagerBuilder.h" 56 57#include "llvm/Target/TargetMachine.h" 58#include "llvm/Target/TargetOptions.h" 59#include "llvm/Support/TargetRegistry.h" 60 61#include "llvm/MC/SubtargetFeature.h" 62 63#include "slang_assert.h" 64#include "slang.h" 65#include "slang_bitcode_gen.h" 66#include "slang_rs_context.h" 67#include "slang_rs_export_foreach.h" 68#include "slang_rs_export_func.h" 69#include "slang_rs_export_reduce.h" 70#include "slang_rs_export_type.h" 71#include "slang_rs_export_var.h" 72#include "slang_rs_metadata.h" 73 74#include "strip_unknown_attributes.h" 75 76namespace slang { 77 78void Backend::CreateFunctionPasses() { 79 if (!mPerFunctionPasses) { 80 mPerFunctionPasses = new llvm::legacy::FunctionPassManager(mpModule); 81 82 llvm::PassManagerBuilder PMBuilder; 83 PMBuilder.OptLevel = mCodeGenOpts.OptimizationLevel; 84 PMBuilder.populateFunctionPassManager(*mPerFunctionPasses); 85 } 86} 87 88void Backend::CreateModulePasses() { 89 if (!mPerModulePasses) { 90 mPerModulePasses = new llvm::legacy::PassManager(); 91 92 llvm::PassManagerBuilder PMBuilder; 93 PMBuilder.OptLevel = mCodeGenOpts.OptimizationLevel; 94 PMBuilder.SizeLevel = mCodeGenOpts.OptimizeSize; 95 if (mCodeGenOpts.UnitAtATime) { 96 PMBuilder.DisableUnitAtATime = 0; 97 } else { 98 PMBuilder.DisableUnitAtATime = 1; 99 } 100 101 if (mCodeGenOpts.UnrollLoops) { 102 PMBuilder.DisableUnrollLoops = 0; 103 } else { 104 PMBuilder.DisableUnrollLoops = 1; 105 } 106 107 PMBuilder.populateModulePassManager(*mPerModulePasses); 108 // Add a pass to strip off unknown/unsupported attributes. 109 mPerModulePasses->add(createStripUnknownAttributesPass()); 110 } 111} 112 113bool Backend::CreateCodeGenPasses() { 114 if ((mOT != Slang::OT_Assembly) && (mOT != Slang::OT_Object)) 115 return true; 116 117 // Now we add passes for code emitting 118 if (mCodeGenPasses) { 119 return true; 120 } else { 121 mCodeGenPasses = new llvm::legacy::FunctionPassManager(mpModule); 122 } 123 124 // Create the TargetMachine for generating code. 125 std::string Triple = mpModule->getTargetTriple(); 126 127 std::string Error; 128 const llvm::Target* TargetInfo = 129 llvm::TargetRegistry::lookupTarget(Triple, Error); 130 if (TargetInfo == nullptr) { 131 mDiagEngine.Report(clang::diag::err_fe_unable_to_create_target) << Error; 132 return false; 133 } 134 135 // Target Machine Options 136 llvm::TargetOptions Options; 137 138 // Use soft-float ABI for ARM (which is the target used by Slang during code 139 // generation). Codegen still uses hardware FPU by default. To use software 140 // floating point, add 'soft-float' feature to FeaturesStr below. 141 Options.FloatABIType = llvm::FloatABI::Soft; 142 143 // BCC needs all unknown symbols resolved at compilation time. So we don't 144 // need any relocation model. 145 llvm::Reloc::Model RM = llvm::Reloc::Static; 146 147 // This is set for the linker (specify how large of the virtual addresses we 148 // can access for all unknown symbols.) 149 llvm::CodeModel::Model CM; 150 if (mpModule->getDataLayout().getPointerSize() == 4) { 151 CM = llvm::CodeModel::Small; 152 } else { 153 // The target may have pointer size greater than 32 (e.g. x86_64 154 // architecture) may need large data address model 155 CM = llvm::CodeModel::Medium; 156 } 157 158 // Setup feature string 159 std::string FeaturesStr; 160 if (mTargetOpts.CPU.size() || mTargetOpts.Features.size()) { 161 llvm::SubtargetFeatures Features; 162 163 for (std::vector<std::string>::const_iterator 164 I = mTargetOpts.Features.begin(), E = mTargetOpts.Features.end(); 165 I != E; 166 I++) 167 Features.AddFeature(*I); 168 169 FeaturesStr = Features.getString(); 170 } 171 172 llvm::TargetMachine *TM = 173 TargetInfo->createTargetMachine(Triple, mTargetOpts.CPU, FeaturesStr, 174 Options, RM, CM); 175 176 // Register scheduler 177 llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler); 178 179 // Register allocation policy: 180 // createFastRegisterAllocator: fast but bad quality 181 // createGreedyRegisterAllocator: not so fast but good quality 182 llvm::RegisterRegAlloc::setDefault((mCodeGenOpts.OptimizationLevel == 0) ? 183 llvm::createFastRegisterAllocator : 184 llvm::createGreedyRegisterAllocator); 185 186 llvm::CodeGenOpt::Level OptLevel = llvm::CodeGenOpt::Default; 187 if (mCodeGenOpts.OptimizationLevel == 0) { 188 OptLevel = llvm::CodeGenOpt::None; 189 } else if (mCodeGenOpts.OptimizationLevel == 3) { 190 OptLevel = llvm::CodeGenOpt::Aggressive; 191 } 192 193 llvm::TargetMachine::CodeGenFileType CGFT = 194 llvm::TargetMachine::CGFT_AssemblyFile; 195 if (mOT == Slang::OT_Object) { 196 CGFT = llvm::TargetMachine::CGFT_ObjectFile; 197 } 198 if (TM->addPassesToEmitFile(*mCodeGenPasses, mBufferOutStream, 199 CGFT, OptLevel)) { 200 mDiagEngine.Report(clang::diag::err_fe_unable_to_interface_with_target); 201 return false; 202 } 203 204 return true; 205} 206 207Backend::Backend(RSContext *Context, clang::DiagnosticsEngine *DiagEngine, 208 const clang::CodeGenOptions &CodeGenOpts, 209 const clang::TargetOptions &TargetOpts, PragmaList *Pragmas, 210 llvm::raw_ostream *OS, Slang::OutputType OT, 211 clang::SourceManager &SourceMgr, bool AllowRSPrefix, 212 bool IsFilterscript) 213 : ASTConsumer(), mTargetOpts(TargetOpts), mpModule(nullptr), mpOS(OS), 214 mOT(OT), mGen(nullptr), mPerFunctionPasses(nullptr), 215 mPerModulePasses(nullptr), mCodeGenPasses(nullptr), 216 mBufferOutStream(*mpOS), mContext(Context), 217 mSourceMgr(SourceMgr), mAllowRSPrefix(AllowRSPrefix), 218 mIsFilterscript(IsFilterscript), mExportVarMetadata(nullptr), 219 mExportFuncMetadata(nullptr), mExportForEachNameMetadata(nullptr), 220 mExportForEachSignatureMetadata(nullptr), mExportReduceMetadata(nullptr), 221 mExportTypeMetadata(nullptr), mRSObjectSlotsMetadata(nullptr), 222 mRefCount(mContext->getASTContext()), 223 mASTChecker(Context, Context->getTargetAPI(), IsFilterscript), 224 mLLVMContext(llvm::getGlobalContext()), mDiagEngine(*DiagEngine), 225 mCodeGenOpts(CodeGenOpts), mPragmas(Pragmas) { 226 mGen = CreateLLVMCodeGen(mDiagEngine, "", mCodeGenOpts, mLLVMContext); 227} 228 229void Backend::Initialize(clang::ASTContext &Ctx) { 230 mGen->Initialize(Ctx); 231 232 mpModule = mGen->GetModule(); 233} 234 235void Backend::HandleTranslationUnit(clang::ASTContext &Ctx) { 236 HandleTranslationUnitPre(Ctx); 237 238 mGen->HandleTranslationUnit(Ctx); 239 240 // Here, we complete a translation unit (whole translation unit is now in LLVM 241 // IR). Now, interact with LLVM backend to generate actual machine code (asm 242 // or machine code, whatever.) 243 244 // Silently ignore if we weren't initialized for some reason. 245 if (!mpModule) 246 return; 247 248 llvm::Module *M = mGen->ReleaseModule(); 249 if (!M) { 250 // The module has been released by IR gen on failures, do not double free. 251 mpModule = nullptr; 252 return; 253 } 254 255 slangAssert(mpModule == M && 256 "Unexpected module change during LLVM IR generation"); 257 258 // Insert #pragma information into metadata section of module 259 if (!mPragmas->empty()) { 260 llvm::NamedMDNode *PragmaMetadata = 261 mpModule->getOrInsertNamedMetadata(Slang::PragmaMetadataName); 262 for (PragmaList::const_iterator I = mPragmas->begin(), E = mPragmas->end(); 263 I != E; 264 I++) { 265 llvm::SmallVector<llvm::Metadata*, 2> Pragma; 266 // Name goes first 267 Pragma.push_back(llvm::MDString::get(mLLVMContext, I->first)); 268 // And then value 269 Pragma.push_back(llvm::MDString::get(mLLVMContext, I->second)); 270 271 // Create MDNode and insert into PragmaMetadata 272 PragmaMetadata->addOperand( 273 llvm::MDNode::get(mLLVMContext, Pragma)); 274 } 275 } 276 277 HandleTranslationUnitPost(mpModule); 278 279 // Create passes for optimization and code emission 280 281 // Create and run per-function passes 282 CreateFunctionPasses(); 283 if (mPerFunctionPasses) { 284 mPerFunctionPasses->doInitialization(); 285 286 for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end(); 287 I != E; 288 I++) 289 if (!I->isDeclaration()) 290 mPerFunctionPasses->run(*I); 291 292 mPerFunctionPasses->doFinalization(); 293 } 294 295 // Create and run module passes 296 CreateModulePasses(); 297 if (mPerModulePasses) 298 mPerModulePasses->run(*mpModule); 299 300 switch (mOT) { 301 case Slang::OT_Assembly: 302 case Slang::OT_Object: { 303 if (!CreateCodeGenPasses()) 304 return; 305 306 mCodeGenPasses->doInitialization(); 307 308 for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end(); 309 I != E; 310 I++) 311 if (!I->isDeclaration()) 312 mCodeGenPasses->run(*I); 313 314 mCodeGenPasses->doFinalization(); 315 break; 316 } 317 case Slang::OT_LLVMAssembly: { 318 llvm::legacy::PassManager *LLEmitPM = new llvm::legacy::PassManager(); 319 LLEmitPM->add(llvm::createPrintModulePass(mBufferOutStream)); 320 LLEmitPM->run(*mpModule); 321 break; 322 } 323 case Slang::OT_Bitcode: { 324 writeBitcode(mBufferOutStream, *mpModule, getTargetAPI(), 325 mCodeGenOpts.OptimizationLevel); 326 break; 327 } 328 case Slang::OT_Nothing: { 329 return; 330 } 331 default: { 332 slangAssert(false && "Unknown output type"); 333 } 334 } 335 336 mBufferOutStream.flush(); 337} 338 339void Backend::HandleTagDeclDefinition(clang::TagDecl *D) { 340 mGen->HandleTagDeclDefinition(D); 341} 342 343void Backend::CompleteTentativeDefinition(clang::VarDecl *D) { 344 mGen->CompleteTentativeDefinition(D); 345} 346 347Backend::~Backend() { 348 delete mpModule; 349 delete mGen; 350 delete mPerFunctionPasses; 351 delete mPerModulePasses; 352 delete mCodeGenPasses; 353} 354 355// 1) Add zero initialization of local RS object types 356void Backend::AnnotateFunction(clang::FunctionDecl *FD) { 357 if (FD && 358 FD->hasBody() && 359 !Slang::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr)) { 360 mRefCount.Init(); 361 mRefCount.Visit(FD->getBody()); 362 } 363} 364 365bool Backend::HandleTopLevelDecl(clang::DeclGroupRef D) { 366 // Disallow user-defined functions with prefix "rs" 367 if (!mAllowRSPrefix) { 368 // Iterate all function declarations in the program. 369 for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end(); 370 I != E; I++) { 371 clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I); 372 if (FD == nullptr) 373 continue; 374 if (!FD->getName().startswith("rs")) // Check prefix 375 continue; 376 if (!Slang::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr)) 377 mContext->ReportError(FD->getLocation(), 378 "invalid function name prefix, " 379 "\"rs\" is reserved: '%0'") 380 << FD->getName(); 381 } 382 } 383 384 // Process any non-static function declarations 385 for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; I++) { 386 clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I); 387 if (FD && FD->isGlobal()) { 388 // Check that we don't have any array parameters being misintrepeted as 389 // kernel pointers due to the C type system's array to pointer decay. 390 size_t numParams = FD->getNumParams(); 391 for (size_t i = 0; i < numParams; i++) { 392 const clang::ParmVarDecl *PVD = FD->getParamDecl(i); 393 clang::QualType QT = PVD->getOriginalType(); 394 if (QT->isArrayType()) { 395 mContext->ReportError( 396 PVD->getTypeSpecStartLoc(), 397 "exported function parameters may not have array type: %0") 398 << QT; 399 } 400 } 401 AnnotateFunction(FD); 402 } 403 } 404 return mGen->HandleTopLevelDecl(D); 405} 406 407void Backend::HandleTranslationUnitPre(clang::ASTContext &C) { 408 clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl(); 409 410 // If we have an invalid RS/FS AST, don't check further. 411 if (!mASTChecker.Validate()) { 412 return; 413 } 414 415 if (mIsFilterscript) { 416 mContext->addPragma("rs_fp_relaxed", ""); 417 } 418 419 int version = mContext->getVersion(); 420 if (version == 0) { 421 // Not setting a version is an error 422 mDiagEngine.Report( 423 mSourceMgr.getLocForEndOfFile(mSourceMgr.getMainFileID()), 424 mDiagEngine.getCustomDiagID( 425 clang::DiagnosticsEngine::Error, 426 "missing pragma for version in source file")); 427 } else { 428 slangAssert(version == 1); 429 } 430 431 if (mContext->getReflectJavaPackageName().empty()) { 432 mDiagEngine.Report( 433 mSourceMgr.getLocForEndOfFile(mSourceMgr.getMainFileID()), 434 mDiagEngine.getCustomDiagID(clang::DiagnosticsEngine::Error, 435 "missing \"#pragma rs " 436 "java_package_name(com.foo.bar)\" " 437 "in source file")); 438 return; 439 } 440 441 // Create a static global destructor if necessary (to handle RS object 442 // runtime cleanup). 443 clang::FunctionDecl *FD = mRefCount.CreateStaticGlobalDtor(); 444 if (FD) { 445 HandleTopLevelDecl(clang::DeclGroupRef(FD)); 446 } 447 448 // Process any static function declarations 449 for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(), 450 E = TUDecl->decls_end(); I != E; I++) { 451 if ((I->getKind() >= clang::Decl::firstFunction) && 452 (I->getKind() <= clang::Decl::lastFunction)) { 453 clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I); 454 if (FD && !FD->isGlobal()) { 455 AnnotateFunction(FD); 456 } 457 } 458 } 459} 460 461/////////////////////////////////////////////////////////////////////////////// 462void Backend::dumpExportVarInfo(llvm::Module *M) { 463 int slotCount = 0; 464 if (mExportVarMetadata == nullptr) 465 mExportVarMetadata = M->getOrInsertNamedMetadata(RS_EXPORT_VAR_MN); 466 467 llvm::SmallVector<llvm::Metadata *, 2> ExportVarInfo; 468 469 // We emit slot information (#rs_object_slots) for any reference counted 470 // RS type or pointer (which can also be bound). 471 472 for (RSContext::const_export_var_iterator I = mContext->export_vars_begin(), 473 E = mContext->export_vars_end(); 474 I != E; 475 I++) { 476 const RSExportVar *EV = *I; 477 const RSExportType *ET = EV->getType(); 478 bool countsAsRSObject = false; 479 480 // Variable name 481 ExportVarInfo.push_back( 482 llvm::MDString::get(mLLVMContext, EV->getName().c_str())); 483 484 // Type name 485 switch (ET->getClass()) { 486 case RSExportType::ExportClassPrimitive: { 487 const RSExportPrimitiveType *PT = 488 static_cast<const RSExportPrimitiveType*>(ET); 489 ExportVarInfo.push_back( 490 llvm::MDString::get( 491 mLLVMContext, llvm::utostr_32(PT->getType()))); 492 if (PT->isRSObjectType()) { 493 countsAsRSObject = true; 494 } 495 break; 496 } 497 case RSExportType::ExportClassPointer: { 498 ExportVarInfo.push_back( 499 llvm::MDString::get( 500 mLLVMContext, ("*" + static_cast<const RSExportPointerType*>(ET) 501 ->getPointeeType()->getName()).c_str())); 502 break; 503 } 504 case RSExportType::ExportClassMatrix: { 505 ExportVarInfo.push_back( 506 llvm::MDString::get( 507 mLLVMContext, llvm::utostr_32( 508 /* TODO Strange value. This pushes just a number, quite 509 * different than the other cases. What is this used for? 510 * These are the metadata values that some partner drivers 511 * want to reference (for TBAA, etc.). We may want to look 512 * at whether these provide any reasonable value (or have 513 * distinct enough values to actually depend on). 514 */ 515 DataTypeRSMatrix2x2 + 516 static_cast<const RSExportMatrixType*>(ET)->getDim() - 2))); 517 break; 518 } 519 case RSExportType::ExportClassVector: 520 case RSExportType::ExportClassConstantArray: 521 case RSExportType::ExportClassRecord: { 522 ExportVarInfo.push_back( 523 llvm::MDString::get(mLLVMContext, 524 EV->getType()->getName().c_str())); 525 break; 526 } 527 } 528 529 mExportVarMetadata->addOperand( 530 llvm::MDNode::get(mLLVMContext, ExportVarInfo)); 531 ExportVarInfo.clear(); 532 533 if (mRSObjectSlotsMetadata == nullptr) { 534 mRSObjectSlotsMetadata = 535 M->getOrInsertNamedMetadata(RS_OBJECT_SLOTS_MN); 536 } 537 538 if (countsAsRSObject) { 539 mRSObjectSlotsMetadata->addOperand(llvm::MDNode::get(mLLVMContext, 540 llvm::MDString::get(mLLVMContext, llvm::utostr_32(slotCount)))); 541 } 542 543 slotCount++; 544 } 545} 546 547void Backend::dumpExportFunctionInfo(llvm::Module *M) { 548 if (mExportFuncMetadata == nullptr) 549 mExportFuncMetadata = 550 M->getOrInsertNamedMetadata(RS_EXPORT_FUNC_MN); 551 552 llvm::SmallVector<llvm::Metadata *, 1> ExportFuncInfo; 553 554 for (RSContext::const_export_func_iterator 555 I = mContext->export_funcs_begin(), 556 E = mContext->export_funcs_end(); 557 I != E; 558 I++) { 559 const RSExportFunc *EF = *I; 560 561 // Function name 562 if (!EF->hasParam()) { 563 ExportFuncInfo.push_back(llvm::MDString::get(mLLVMContext, 564 EF->getName().c_str())); 565 } else { 566 llvm::Function *F = M->getFunction(EF->getName()); 567 llvm::Function *HelperFunction; 568 const std::string HelperFunctionName(".helper_" + EF->getName()); 569 570 slangAssert(F && "Function marked as exported disappeared in Bitcode"); 571 572 // Create helper function 573 { 574 llvm::StructType *HelperFunctionParameterTy = nullptr; 575 std::vector<bool> isStructInput; 576 577 if (!F->getArgumentList().empty()) { 578 std::vector<llvm::Type*> HelperFunctionParameterTys; 579 for (llvm::Function::arg_iterator AI = F->arg_begin(), 580 AE = F->arg_end(); AI != AE; AI++) { 581 if (AI->getType()->isPointerTy() && AI->getType()->getPointerElementType()->isStructTy()) { 582 HelperFunctionParameterTys.push_back(AI->getType()->getPointerElementType()); 583 isStructInput.push_back(true); 584 } else { 585 HelperFunctionParameterTys.push_back(AI->getType()); 586 isStructInput.push_back(false); 587 } 588 } 589 HelperFunctionParameterTy = 590 llvm::StructType::get(mLLVMContext, HelperFunctionParameterTys); 591 } 592 593 if (!EF->checkParameterPacketType(HelperFunctionParameterTy)) { 594 fprintf(stderr, "Failed to export function %s: parameter type " 595 "mismatch during creation of helper function.\n", 596 EF->getName().c_str()); 597 598 const RSExportRecordType *Expected = EF->getParamPacketType(); 599 if (Expected) { 600 fprintf(stderr, "Expected:\n"); 601 Expected->getLLVMType()->dump(); 602 } 603 if (HelperFunctionParameterTy) { 604 fprintf(stderr, "Got:\n"); 605 HelperFunctionParameterTy->dump(); 606 } 607 } 608 609 std::vector<llvm::Type*> Params; 610 if (HelperFunctionParameterTy) { 611 llvm::PointerType *HelperFunctionParameterTyP = 612 llvm::PointerType::getUnqual(HelperFunctionParameterTy); 613 Params.push_back(HelperFunctionParameterTyP); 614 } 615 616 llvm::FunctionType * HelperFunctionType = 617 llvm::FunctionType::get(F->getReturnType(), 618 Params, 619 /* IsVarArgs = */false); 620 621 HelperFunction = 622 llvm::Function::Create(HelperFunctionType, 623 llvm::GlobalValue::ExternalLinkage, 624 HelperFunctionName, 625 M); 626 627 HelperFunction->addFnAttr(llvm::Attribute::NoInline); 628 HelperFunction->setCallingConv(F->getCallingConv()); 629 630 // Create helper function body 631 { 632 llvm::Argument *HelperFunctionParameter = 633 &(*HelperFunction->arg_begin()); 634 llvm::BasicBlock *BB = 635 llvm::BasicBlock::Create(mLLVMContext, "entry", HelperFunction); 636 llvm::IRBuilder<> *IB = new llvm::IRBuilder<>(BB); 637 llvm::SmallVector<llvm::Value*, 6> Params; 638 llvm::Value *Idx[2]; 639 640 Idx[0] = 641 llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), 0); 642 643 // getelementptr and load instruction for all elements in 644 // parameter .p 645 for (size_t i = 0; i < EF->getNumParameters(); i++) { 646 // getelementptr 647 Idx[1] = llvm::ConstantInt::get( 648 llvm::Type::getInt32Ty(mLLVMContext), i); 649 650 llvm::Value *Ptr = NULL; 651 652 Ptr = IB->CreateInBoundsGEP(HelperFunctionParameter, Idx); 653 654 // Load is only required for non-struct ptrs 655 if (isStructInput[i]) { 656 Params.push_back(Ptr); 657 } else { 658 llvm::Value *V = IB->CreateLoad(Ptr); 659 Params.push_back(V); 660 } 661 } 662 663 // Call and pass the all elements as parameter to F 664 llvm::CallInst *CI = IB->CreateCall(F, Params); 665 666 CI->setCallingConv(F->getCallingConv()); 667 668 if (F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext)) 669 IB->CreateRetVoid(); 670 else 671 IB->CreateRet(CI); 672 673 delete IB; 674 } 675 } 676 677 ExportFuncInfo.push_back( 678 llvm::MDString::get(mLLVMContext, HelperFunctionName.c_str())); 679 } 680 681 mExportFuncMetadata->addOperand( 682 llvm::MDNode::get(mLLVMContext, ExportFuncInfo)); 683 ExportFuncInfo.clear(); 684 } 685} 686 687void Backend::dumpExportForEachInfo(llvm::Module *M) { 688 if (mExportForEachNameMetadata == nullptr) { 689 mExportForEachNameMetadata = 690 M->getOrInsertNamedMetadata(RS_EXPORT_FOREACH_NAME_MN); 691 } 692 if (mExportForEachSignatureMetadata == nullptr) { 693 mExportForEachSignatureMetadata = 694 M->getOrInsertNamedMetadata(RS_EXPORT_FOREACH_MN); 695 } 696 697 llvm::SmallVector<llvm::Metadata *, 1> ExportForEachName; 698 llvm::SmallVector<llvm::Metadata *, 1> ExportForEachInfo; 699 700 for (RSContext::const_export_foreach_iterator 701 I = mContext->export_foreach_begin(), 702 E = mContext->export_foreach_end(); 703 I != E; 704 I++) { 705 const RSExportForEach *EFE = *I; 706 707 ExportForEachName.push_back( 708 llvm::MDString::get(mLLVMContext, EFE->getName().c_str())); 709 710 mExportForEachNameMetadata->addOperand( 711 llvm::MDNode::get(mLLVMContext, ExportForEachName)); 712 ExportForEachName.clear(); 713 714 ExportForEachInfo.push_back( 715 llvm::MDString::get(mLLVMContext, 716 llvm::utostr_32(EFE->getSignatureMetadata()))); 717 718 mExportForEachSignatureMetadata->addOperand( 719 llvm::MDNode::get(mLLVMContext, ExportForEachInfo)); 720 ExportForEachInfo.clear(); 721 } 722} 723 724void Backend::dumpExportReduceInfo(llvm::Module *M) { 725 if (!mExportReduceMetadata) { 726 mExportReduceMetadata = M->getOrInsertNamedMetadata(RS_EXPORT_REDUCE_MN); 727 } 728 729 llvm::SmallVector<llvm::Metadata *, 1> ExportReduceInfo; 730 731 // Add the names of the reduce-style kernel functions to the metadata node. 732 for (auto I = mContext->export_reduce_begin(), 733 E = mContext->export_reduce_end(); I != E; ++I) { 734 ExportReduceInfo.clear(); 735 736 ExportReduceInfo.push_back( 737 llvm::MDString::get(mLLVMContext, (*I)->getName().c_str())); 738 739 mExportReduceMetadata->addOperand( 740 llvm::MDNode::get(mLLVMContext, ExportReduceInfo)); 741 } 742} 743 744void Backend::dumpExportTypeInfo(llvm::Module *M) { 745 llvm::SmallVector<llvm::Metadata *, 1> ExportTypeInfo; 746 747 for (RSContext::const_export_type_iterator 748 I = mContext->export_types_begin(), 749 E = mContext->export_types_end(); 750 I != E; 751 I++) { 752 // First, dump type name list to export 753 const RSExportType *ET = I->getValue(); 754 755 ExportTypeInfo.clear(); 756 // Type name 757 ExportTypeInfo.push_back( 758 llvm::MDString::get(mLLVMContext, ET->getName().c_str())); 759 760 if (ET->getClass() == RSExportType::ExportClassRecord) { 761 const RSExportRecordType *ERT = 762 static_cast<const RSExportRecordType*>(ET); 763 764 if (mExportTypeMetadata == nullptr) 765 mExportTypeMetadata = 766 M->getOrInsertNamedMetadata(RS_EXPORT_TYPE_MN); 767 768 mExportTypeMetadata->addOperand( 769 llvm::MDNode::get(mLLVMContext, ExportTypeInfo)); 770 771 // Now, export struct field information to %[struct name] 772 std::string StructInfoMetadataName("%"); 773 StructInfoMetadataName.append(ET->getName()); 774 llvm::NamedMDNode *StructInfoMetadata = 775 M->getOrInsertNamedMetadata(StructInfoMetadataName); 776 llvm::SmallVector<llvm::Metadata *, 3> FieldInfo; 777 778 slangAssert(StructInfoMetadata->getNumOperands() == 0 && 779 "Metadata with same name was created before"); 780 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(), 781 FE = ERT->fields_end(); 782 FI != FE; 783 FI++) { 784 const RSExportRecordType::Field *F = *FI; 785 786 // 1. field name 787 FieldInfo.push_back(llvm::MDString::get(mLLVMContext, 788 F->getName().c_str())); 789 790 // 2. field type name 791 FieldInfo.push_back( 792 llvm::MDString::get(mLLVMContext, 793 F->getType()->getName().c_str())); 794 795 StructInfoMetadata->addOperand( 796 llvm::MDNode::get(mLLVMContext, FieldInfo)); 797 FieldInfo.clear(); 798 } 799 } // ET->getClass() == RSExportType::ExportClassRecord 800 } 801} 802 803void Backend::HandleTranslationUnitPost(llvm::Module *M) { 804 805 if (!mContext->is64Bit()) { 806 M->setDataLayout("e-p:32:32-i64:64-v128:64:128-n32-S64"); 807 } 808 809 if (!mContext->processExport()) { 810 return; 811 } 812 813 if (mContext->hasExportVar()) 814 dumpExportVarInfo(M); 815 816 if (mContext->hasExportFunc()) 817 dumpExportFunctionInfo(M); 818 819 if (mContext->hasExportForEach()) 820 dumpExportForEachInfo(M); 821 822 if (mContext->hasExportReduce()) 823 dumpExportReduceInfo(M); 824 825 if (mContext->hasExportType()) 826 dumpExportTypeInfo(M); 827} 828 829} // namespace slang 830