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