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