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