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