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