slang_backend.cpp revision 2615f383dfc1542a05f19aee23b03a09bd018f4e
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      mExportReduceNewMetadata(nullptr),
224      mExportTypeMetadata(nullptr), mRSObjectSlotsMetadata(nullptr),
225      mRefCount(mContext->getASTContext()),
226      mASTChecker(Context, Context->getTargetAPI(), IsFilterscript),
227      mForEachHandler(Context),
228      mLLVMContext(llvm::getGlobalContext()), mDiagEngine(*DiagEngine),
229      mCodeGenOpts(CodeGenOpts), mPragmas(Pragmas) {
230  mGen = CreateLLVMCodeGen(mDiagEngine, "", mCodeGenOpts, mLLVMContext);
231}
232
233void Backend::Initialize(clang::ASTContext &Ctx) {
234  mGen->Initialize(Ctx);
235
236  mpModule = mGen->GetModule();
237}
238
239void Backend::HandleTranslationUnit(clang::ASTContext &Ctx) {
240  HandleTranslationUnitPre(Ctx);
241
242  if (mASTPrint)
243    Ctx.getTranslationUnitDecl()->dump();
244
245  mGen->HandleTranslationUnit(Ctx);
246
247  // Here, we complete a translation unit (whole translation unit is now in LLVM
248  // IR). Now, interact with LLVM backend to generate actual machine code (asm
249  // or machine code, whatever.)
250
251  // Silently ignore if we weren't initialized for some reason.
252  if (!mpModule)
253    return;
254
255  llvm::Module *M = mGen->ReleaseModule();
256  if (!M) {
257    // The module has been released by IR gen on failures, do not double free.
258    mpModule = nullptr;
259    return;
260  }
261
262  slangAssert(mpModule == M &&
263              "Unexpected module change during LLVM IR generation");
264
265  // Insert #pragma information into metadata section of module
266  if (!mPragmas->empty()) {
267    llvm::NamedMDNode *PragmaMetadata =
268        mpModule->getOrInsertNamedMetadata(Slang::PragmaMetadataName);
269    for (PragmaList::const_iterator I = mPragmas->begin(), E = mPragmas->end();
270         I != E;
271         I++) {
272      llvm::SmallVector<llvm::Metadata*, 2> Pragma;
273      // Name goes first
274      Pragma.push_back(llvm::MDString::get(mLLVMContext, I->first));
275      // And then value
276      Pragma.push_back(llvm::MDString::get(mLLVMContext, I->second));
277
278      // Create MDNode and insert into PragmaMetadata
279      PragmaMetadata->addOperand(
280          llvm::MDNode::get(mLLVMContext, Pragma));
281    }
282  }
283
284  HandleTranslationUnitPost(mpModule);
285
286  // Create passes for optimization and code emission
287
288  // Create and run per-function passes
289  CreateFunctionPasses();
290  if (mPerFunctionPasses) {
291    mPerFunctionPasses->doInitialization();
292
293    for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end();
294         I != E;
295         I++)
296      if (!I->isDeclaration())
297        mPerFunctionPasses->run(*I);
298
299    mPerFunctionPasses->doFinalization();
300  }
301
302  // Create and run module passes
303  CreateModulePasses();
304  if (mPerModulePasses)
305    mPerModulePasses->run(*mpModule);
306
307  switch (mOT) {
308    case Slang::OT_Assembly:
309    case Slang::OT_Object: {
310      if (!CreateCodeGenPasses())
311        return;
312
313      mCodeGenPasses->doInitialization();
314
315      for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end();
316          I != E;
317          I++)
318        if (!I->isDeclaration())
319          mCodeGenPasses->run(*I);
320
321      mCodeGenPasses->doFinalization();
322      break;
323    }
324    case Slang::OT_LLVMAssembly: {
325      llvm::legacy::PassManager *LLEmitPM = new llvm::legacy::PassManager();
326      LLEmitPM->add(llvm::createPrintModulePass(mBufferOutStream));
327      LLEmitPM->run(*mpModule);
328      break;
329    }
330    case Slang::OT_Bitcode: {
331      writeBitcode(mBufferOutStream, *mpModule, getTargetAPI(),
332                   mCodeGenOpts.OptimizationLevel, mCodeGenOpts.getDebugInfo());
333      break;
334    }
335    case Slang::OT_Nothing: {
336      return;
337    }
338    default: {
339      slangAssert(false && "Unknown output type");
340    }
341  }
342
343  mBufferOutStream.flush();
344}
345
346void Backend::HandleTagDeclDefinition(clang::TagDecl *D) {
347  mGen->HandleTagDeclDefinition(D);
348}
349
350void Backend::CompleteTentativeDefinition(clang::VarDecl *D) {
351  mGen->CompleteTentativeDefinition(D);
352}
353
354Backend::~Backend() {
355  delete mpModule;
356  delete mGen;
357  delete mPerFunctionPasses;
358  delete mPerModulePasses;
359  delete mCodeGenPasses;
360}
361
362// 1) Add zero initialization of local RS object types
363void Backend::AnnotateFunction(clang::FunctionDecl *FD) {
364  if (FD &&
365      FD->hasBody() &&
366      !Slang::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr)) {
367    mRefCount.Init();
368    mRefCount.Visit(FD->getBody());
369  }
370}
371
372void Backend::LowerRSForEachCall(clang::FunctionDecl *FD) {
373  // Skip this AST walking for lower API levels.
374  if (getTargetAPI() < SLANG_DEVELOPMENT_TARGET_API) {
375    return;
376  }
377
378  if (!FD || !FD->hasBody() ||
379      Slang::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr)) {
380    return;
381  }
382
383  mForEachHandler.VisitStmt(FD->getBody());
384}
385
386bool Backend::HandleTopLevelDecl(clang::DeclGroupRef D) {
387  // Find and remember the types for rs_allocation and rs_script_call_t so
388  // they can be used later for translating rsForEach() calls.
389  for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end();
390       (mContext->getAllocationType().isNull() ||
391        mContext->getScriptCallType().isNull()) &&
392       I != E; I++) {
393    if (clang::TypeDecl* TD = llvm::dyn_cast<clang::TypeDecl>(*I)) {
394      clang::StringRef TypeName = TD->getName();
395      if (TypeName.equals("rs_allocation")) {
396        mContext->setAllocationType(TD);
397      } else if (TypeName.equals("rs_script_call_t")) {
398        mContext->setScriptCallType(TD);
399      }
400    }
401  }
402
403  // Disallow user-defined functions with prefix "rs"
404  if (!mAllowRSPrefix) {
405    // Iterate all function declarations in the program.
406    for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end();
407         I != E; I++) {
408      clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
409      if (FD == nullptr)
410        continue;
411      if (!FD->getName().startswith("rs"))  // Check prefix
412        continue;
413      if (!Slang::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr))
414        mContext->ReportError(FD->getLocation(),
415                              "invalid function name prefix, "
416                              "\"rs\" is reserved: '%0'")
417            << FD->getName();
418    }
419  }
420
421  for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; I++) {
422    clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
423    // Process any non-static function declarations
424    if (FD && FD->isGlobal()) {
425      // Check that we don't have any array parameters being misintrepeted as
426      // kernel pointers due to the C type system's array to pointer decay.
427      size_t numParams = FD->getNumParams();
428      for (size_t i = 0; i < numParams; i++) {
429        const clang::ParmVarDecl *PVD = FD->getParamDecl(i);
430        clang::QualType QT = PVD->getOriginalType();
431        if (QT->isArrayType()) {
432          mContext->ReportError(
433              PVD->getTypeSpecStartLoc(),
434              "exported function parameters may not have array type: %0")
435              << QT;
436        }
437      }
438      AnnotateFunction(FD);
439    }
440
441    if (getTargetAPI() == SLANG_DEVELOPMENT_TARGET_API) {
442      if (FD && FD->hasBody() &&
443          RSExportForEach::isRSForEachFunc(getTargetAPI(), FD)) {
444        // Log kernels by their names, and assign them slot numbers.
445        if (!Slang::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr)) {
446            mContext->addForEach(FD);
447        }
448      } else {
449        // Look for any kernel launch calls and translate them into using the
450        // internal API.
451        // TODO: Simply ignores kernel launch inside a kernel for now.
452        // Needs more rigorous and comprehensive checks.
453        LowerRSForEachCall(FD);
454      }
455    }
456  }
457
458  return mGen->HandleTopLevelDecl(D);
459}
460
461void Backend::HandleTranslationUnitPre(clang::ASTContext &C) {
462  clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
463
464  // If we have an invalid RS/FS AST, don't check further.
465  if (!mASTChecker.Validate()) {
466    return;
467  }
468
469  if (mIsFilterscript) {
470    mContext->addPragma("rs_fp_relaxed", "");
471  }
472
473  int version = mContext->getVersion();
474  if (version == 0) {
475    // Not setting a version is an error
476    mDiagEngine.Report(
477        mSourceMgr.getLocForEndOfFile(mSourceMgr.getMainFileID()),
478        mDiagEngine.getCustomDiagID(
479            clang::DiagnosticsEngine::Error,
480            "missing pragma for version in source file"));
481  } else {
482    slangAssert(version == 1);
483  }
484
485  if (mContext->getReflectJavaPackageName().empty()) {
486    mDiagEngine.Report(
487        mSourceMgr.getLocForEndOfFile(mSourceMgr.getMainFileID()),
488        mDiagEngine.getCustomDiagID(clang::DiagnosticsEngine::Error,
489                                    "missing \"#pragma rs "
490                                    "java_package_name(com.foo.bar)\" "
491                                    "in source file"));
492    return;
493  }
494
495  // Create a static global destructor if necessary (to handle RS object
496  // runtime cleanup).
497  clang::FunctionDecl *FD = mRefCount.CreateStaticGlobalDtor();
498  if (FD) {
499    HandleTopLevelDecl(clang::DeclGroupRef(FD));
500  }
501
502  // Process any static function declarations
503  for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
504          E = TUDecl->decls_end(); I != E; I++) {
505    if ((I->getKind() >= clang::Decl::firstFunction) &&
506        (I->getKind() <= clang::Decl::lastFunction)) {
507      clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
508      if (FD && !FD->isGlobal()) {
509        AnnotateFunction(FD);
510      }
511    }
512  }
513}
514
515///////////////////////////////////////////////////////////////////////////////
516void Backend::dumpExportVarInfo(llvm::Module *M) {
517  int slotCount = 0;
518  if (mExportVarMetadata == nullptr)
519    mExportVarMetadata = M->getOrInsertNamedMetadata(RS_EXPORT_VAR_MN);
520
521  llvm::SmallVector<llvm::Metadata *, 2> ExportVarInfo;
522
523  // We emit slot information (#rs_object_slots) for any reference counted
524  // RS type or pointer (which can also be bound).
525
526  for (RSContext::const_export_var_iterator I = mContext->export_vars_begin(),
527          E = mContext->export_vars_end();
528       I != E;
529       I++) {
530    const RSExportVar *EV = *I;
531    const RSExportType *ET = EV->getType();
532    bool countsAsRSObject = false;
533
534    // Variable name
535    ExportVarInfo.push_back(
536        llvm::MDString::get(mLLVMContext, EV->getName().c_str()));
537
538    // Type name
539    switch (ET->getClass()) {
540      case RSExportType::ExportClassPrimitive: {
541        const RSExportPrimitiveType *PT =
542            static_cast<const RSExportPrimitiveType*>(ET);
543        ExportVarInfo.push_back(
544            llvm::MDString::get(
545              mLLVMContext, llvm::utostr_32(PT->getType())));
546        if (PT->isRSObjectType()) {
547          countsAsRSObject = true;
548        }
549        break;
550      }
551      case RSExportType::ExportClassPointer: {
552        ExportVarInfo.push_back(
553            llvm::MDString::get(
554              mLLVMContext, ("*" + static_cast<const RSExportPointerType*>(ET)
555                ->getPointeeType()->getName()).c_str()));
556        break;
557      }
558      case RSExportType::ExportClassMatrix: {
559        ExportVarInfo.push_back(
560            llvm::MDString::get(
561              mLLVMContext, llvm::utostr_32(
562                  /* TODO Strange value.  This pushes just a number, quite
563                   * different than the other cases.  What is this used for?
564                   * These are the metadata values that some partner drivers
565                   * want to reference (for TBAA, etc.). We may want to look
566                   * at whether these provide any reasonable value (or have
567                   * distinct enough values to actually depend on).
568                   */
569                DataTypeRSMatrix2x2 +
570                static_cast<const RSExportMatrixType*>(ET)->getDim() - 2)));
571        break;
572      }
573      case RSExportType::ExportClassVector:
574      case RSExportType::ExportClassConstantArray:
575      case RSExportType::ExportClassRecord: {
576        ExportVarInfo.push_back(
577            llvm::MDString::get(mLLVMContext,
578              EV->getType()->getName().c_str()));
579        break;
580      }
581    }
582
583    mExportVarMetadata->addOperand(
584        llvm::MDNode::get(mLLVMContext, ExportVarInfo));
585    ExportVarInfo.clear();
586
587    if (mRSObjectSlotsMetadata == nullptr) {
588      mRSObjectSlotsMetadata =
589          M->getOrInsertNamedMetadata(RS_OBJECT_SLOTS_MN);
590    }
591
592    if (countsAsRSObject) {
593      mRSObjectSlotsMetadata->addOperand(llvm::MDNode::get(mLLVMContext,
594          llvm::MDString::get(mLLVMContext, llvm::utostr_32(slotCount))));
595    }
596
597    slotCount++;
598  }
599}
600
601void Backend::dumpExportFunctionInfo(llvm::Module *M) {
602  if (mExportFuncMetadata == nullptr)
603    mExportFuncMetadata =
604        M->getOrInsertNamedMetadata(RS_EXPORT_FUNC_MN);
605
606  llvm::SmallVector<llvm::Metadata *, 1> ExportFuncInfo;
607
608  for (RSContext::const_export_func_iterator
609          I = mContext->export_funcs_begin(),
610          E = mContext->export_funcs_end();
611       I != E;
612       I++) {
613    const RSExportFunc *EF = *I;
614
615    // Function name
616    if (!EF->hasParam()) {
617      ExportFuncInfo.push_back(llvm::MDString::get(mLLVMContext,
618                                                   EF->getName().c_str()));
619    } else {
620      llvm::Function *F = M->getFunction(EF->getName());
621      llvm::Function *HelperFunction;
622      const std::string HelperFunctionName(".helper_" + EF->getName());
623
624      slangAssert(F && "Function marked as exported disappeared in Bitcode");
625
626      // Create helper function
627      {
628        llvm::StructType *HelperFunctionParameterTy = nullptr;
629        std::vector<bool> isStructInput;
630
631        if (!F->getArgumentList().empty()) {
632          std::vector<llvm::Type*> HelperFunctionParameterTys;
633          for (llvm::Function::arg_iterator AI = F->arg_begin(),
634                   AE = F->arg_end(); AI != AE; AI++) {
635              if (AI->getType()->isPointerTy() && AI->getType()->getPointerElementType()->isStructTy()) {
636                  HelperFunctionParameterTys.push_back(AI->getType()->getPointerElementType());
637                  isStructInput.push_back(true);
638              } else {
639                  HelperFunctionParameterTys.push_back(AI->getType());
640                  isStructInput.push_back(false);
641              }
642          }
643          HelperFunctionParameterTy =
644              llvm::StructType::get(mLLVMContext, HelperFunctionParameterTys);
645        }
646
647        if (!EF->checkParameterPacketType(HelperFunctionParameterTy)) {
648          fprintf(stderr, "Failed to export function %s: parameter type "
649                          "mismatch during creation of helper function.\n",
650                  EF->getName().c_str());
651
652          const RSExportRecordType *Expected = EF->getParamPacketType();
653          if (Expected) {
654            fprintf(stderr, "Expected:\n");
655            Expected->getLLVMType()->dump();
656          }
657          if (HelperFunctionParameterTy) {
658            fprintf(stderr, "Got:\n");
659            HelperFunctionParameterTy->dump();
660          }
661        }
662
663        std::vector<llvm::Type*> Params;
664        if (HelperFunctionParameterTy) {
665          llvm::PointerType *HelperFunctionParameterTyP =
666              llvm::PointerType::getUnqual(HelperFunctionParameterTy);
667          Params.push_back(HelperFunctionParameterTyP);
668        }
669
670        llvm::FunctionType * HelperFunctionType =
671            llvm::FunctionType::get(F->getReturnType(),
672                                    Params,
673                                    /* IsVarArgs = */false);
674
675        HelperFunction =
676            llvm::Function::Create(HelperFunctionType,
677                                   llvm::GlobalValue::ExternalLinkage,
678                                   HelperFunctionName,
679                                   M);
680
681        HelperFunction->addFnAttr(llvm::Attribute::NoInline);
682        HelperFunction->setCallingConv(F->getCallingConv());
683
684        // Create helper function body
685        {
686          llvm::Argument *HelperFunctionParameter =
687              &(*HelperFunction->arg_begin());
688          llvm::BasicBlock *BB =
689              llvm::BasicBlock::Create(mLLVMContext, "entry", HelperFunction);
690          llvm::IRBuilder<> *IB = new llvm::IRBuilder<>(BB);
691          llvm::SmallVector<llvm::Value*, 6> Params;
692          llvm::Value *Idx[2];
693
694          Idx[0] =
695              llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), 0);
696
697          // getelementptr and load instruction for all elements in
698          // parameter .p
699          for (size_t i = 0; i < EF->getNumParameters(); i++) {
700            // getelementptr
701            Idx[1] = llvm::ConstantInt::get(
702              llvm::Type::getInt32Ty(mLLVMContext), i);
703
704            llvm::Value *Ptr = NULL;
705
706            Ptr = IB->CreateInBoundsGEP(HelperFunctionParameter, Idx);
707
708            // Load is only required for non-struct ptrs
709            if (isStructInput[i]) {
710                Params.push_back(Ptr);
711            } else {
712                llvm::Value *V = IB->CreateLoad(Ptr);
713                Params.push_back(V);
714            }
715          }
716
717          // Call and pass the all elements as parameter to F
718          llvm::CallInst *CI = IB->CreateCall(F, Params);
719
720          CI->setCallingConv(F->getCallingConv());
721
722          if (F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext)) {
723            IB->CreateRetVoid();
724          } else {
725            IB->CreateRet(CI);
726          }
727
728          delete IB;
729        }
730      }
731
732      ExportFuncInfo.push_back(
733          llvm::MDString::get(mLLVMContext, HelperFunctionName.c_str()));
734    }
735
736    mExportFuncMetadata->addOperand(
737        llvm::MDNode::get(mLLVMContext, ExportFuncInfo));
738    ExportFuncInfo.clear();
739  }
740}
741
742void Backend::dumpExportForEachInfo(llvm::Module *M) {
743  if (mExportForEachNameMetadata == nullptr) {
744    mExportForEachNameMetadata =
745        M->getOrInsertNamedMetadata(RS_EXPORT_FOREACH_NAME_MN);
746  }
747  if (mExportForEachSignatureMetadata == nullptr) {
748    mExportForEachSignatureMetadata =
749        M->getOrInsertNamedMetadata(RS_EXPORT_FOREACH_MN);
750  }
751
752  llvm::SmallVector<llvm::Metadata *, 1> ExportForEachName;
753  llvm::SmallVector<llvm::Metadata *, 1> ExportForEachInfo;
754
755  for (RSContext::const_export_foreach_iterator
756          I = mContext->export_foreach_begin(),
757          E = mContext->export_foreach_end();
758       I != E;
759       I++) {
760    const RSExportForEach *EFE = *I;
761
762    ExportForEachName.push_back(
763        llvm::MDString::get(mLLVMContext, EFE->getName().c_str()));
764
765    mExportForEachNameMetadata->addOperand(
766        llvm::MDNode::get(mLLVMContext, ExportForEachName));
767    ExportForEachName.clear();
768
769    ExportForEachInfo.push_back(
770        llvm::MDString::get(mLLVMContext,
771                            llvm::utostr_32(EFE->getSignatureMetadata())));
772
773    mExportForEachSignatureMetadata->addOperand(
774        llvm::MDNode::get(mLLVMContext, ExportForEachInfo));
775    ExportForEachInfo.clear();
776  }
777}
778
779void Backend::dumpExportReduceInfo(llvm::Module *M) {
780  if (!mExportReduceMetadata) {
781    mExportReduceMetadata = M->getOrInsertNamedMetadata(RS_EXPORT_REDUCE_MN);
782  }
783
784  llvm::SmallVector<llvm::Metadata *, 1> ExportReduceInfo;
785
786  // Add the names of the reduce-style kernel functions to the metadata node.
787  for (auto I = mContext->export_reduce_begin(),
788            E = mContext->export_reduce_end(); I != E; ++I) {
789    ExportReduceInfo.clear();
790
791    ExportReduceInfo.push_back(
792      llvm::MDString::get(mLLVMContext, (*I)->getName().c_str()));
793
794    mExportReduceMetadata->addOperand(
795      llvm::MDNode::get(mLLVMContext, ExportReduceInfo));
796  }
797}
798
799void Backend::dumpExportReduceNewInfo(llvm::Module *M) {
800  if (!mExportReduceNewMetadata) {
801    mExportReduceNewMetadata =
802      M->getOrInsertNamedMetadata(RS_EXPORT_REDUCE_NEW_MN);
803  }
804
805  llvm::SmallVector<llvm::Metadata *, 6> ExportReduceNewInfo;
806  // Add operand to ExportReduceNewInfo, padding out missing operands with
807  // nullptr.
808  auto addOperand = [&ExportReduceNewInfo](uint32_t Idx, llvm::Metadata *N) {
809    while (Idx > ExportReduceNewInfo.size())
810      ExportReduceNewInfo.push_back(nullptr);
811    ExportReduceNewInfo.push_back(N);
812  };
813  // Add string operand to ExportReduceNewInfo, padding out missing operands
814  // with nullptr.
815  // If string is empty, then do not add it unless Always is true.
816  auto addString = [&addOperand, this](uint32_t Idx, const std::string &S,
817                                       bool Always = true) {
818    if (Always || !S.empty())
819      addOperand(Idx, llvm::MDString::get(mLLVMContext, S));
820  };
821
822  // Add the description of the reduction kernels to the metadata node.
823  for (auto I = mContext->export_reduce_new_begin(),
824            E = mContext->export_reduce_new_end();
825       I != E; ++I) {
826    ExportReduceNewInfo.clear();
827
828    addString(0, (*I)->getNameReduce());
829    addString(1, (*I)->getNameInitializer());
830
831    llvm::SmallVector<llvm::Metadata *, 2> Accumulator;
832    Accumulator.push_back(
833      llvm::MDString::get(mLLVMContext, (*I)->getNameAccumulator()));
834    Accumulator.push_back(llvm::MDString::get(
835      mLLVMContext,
836      llvm::utostr_32(0))); // TODO: emit actual accumulator signature bits
837    addOperand(2, llvm::MDTuple::get(mLLVMContext, Accumulator));
838
839    addString(3, (*I)->getNameCombiner(), false);
840    addString(4, (*I)->getNameOutConverter(), false);
841    addString(5, (*I)->getNameHalter(), false);
842
843    mExportReduceNewMetadata->addOperand(
844      llvm::MDTuple::get(mLLVMContext, ExportReduceNewInfo));
845  }
846}
847
848void Backend::dumpExportTypeInfo(llvm::Module *M) {
849  llvm::SmallVector<llvm::Metadata *, 1> ExportTypeInfo;
850
851  for (RSContext::const_export_type_iterator
852          I = mContext->export_types_begin(),
853          E = mContext->export_types_end();
854       I != E;
855       I++) {
856    // First, dump type name list to export
857    const RSExportType *ET = I->getValue();
858
859    ExportTypeInfo.clear();
860    // Type name
861    ExportTypeInfo.push_back(
862        llvm::MDString::get(mLLVMContext, ET->getName().c_str()));
863
864    if (ET->getClass() == RSExportType::ExportClassRecord) {
865      const RSExportRecordType *ERT =
866          static_cast<const RSExportRecordType*>(ET);
867
868      if (mExportTypeMetadata == nullptr)
869        mExportTypeMetadata =
870            M->getOrInsertNamedMetadata(RS_EXPORT_TYPE_MN);
871
872      mExportTypeMetadata->addOperand(
873          llvm::MDNode::get(mLLVMContext, ExportTypeInfo));
874
875      // Now, export struct field information to %[struct name]
876      std::string StructInfoMetadataName("%");
877      StructInfoMetadataName.append(ET->getName());
878      llvm::NamedMDNode *StructInfoMetadata =
879          M->getOrInsertNamedMetadata(StructInfoMetadataName);
880      llvm::SmallVector<llvm::Metadata *, 3> FieldInfo;
881
882      slangAssert(StructInfoMetadata->getNumOperands() == 0 &&
883                  "Metadata with same name was created before");
884      for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
885              FE = ERT->fields_end();
886           FI != FE;
887           FI++) {
888        const RSExportRecordType::Field *F = *FI;
889
890        // 1. field name
891        FieldInfo.push_back(llvm::MDString::get(mLLVMContext,
892                                                F->getName().c_str()));
893
894        // 2. field type name
895        FieldInfo.push_back(
896            llvm::MDString::get(mLLVMContext,
897                                F->getType()->getName().c_str()));
898
899        StructInfoMetadata->addOperand(
900            llvm::MDNode::get(mLLVMContext, FieldInfo));
901        FieldInfo.clear();
902      }
903    }   // ET->getClass() == RSExportType::ExportClassRecord
904  }
905}
906
907void Backend::HandleTranslationUnitPost(llvm::Module *M) {
908
909  if (!mContext->is64Bit()) {
910    M->setDataLayout("e-p:32:32-i64:64-v128:64:128-n32-S64");
911  }
912
913  if (!mContext->processExports()) {
914    return;
915  }
916
917  if (mContext->hasExportVar())
918    dumpExportVarInfo(M);
919
920  if (mContext->hasExportFunc())
921    dumpExportFunctionInfo(M);
922
923  if (mContext->hasExportForEach())
924    dumpExportForEachInfo(M);
925
926  if (mContext->hasExportReduce())
927    dumpExportReduceInfo(M);
928
929  if (mContext->hasExportReduceNew())
930    dumpExportReduceNewInfo(M);
931
932  if (mContext->hasExportType())
933    dumpExportTypeInfo(M);
934}
935
936}  // namespace slang
937