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 
79 namespace slang {
80 
CreateFunctionPasses()81 void 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 
CreateModulePasses()91 void 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 
CreateCodeGenPasses()116 bool 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 
Backend(RSContext * Context,clang::DiagnosticsEngine * DiagEngine,const clang::CodeGenOptions & CodeGenOpts,const clang::TargetOptions & TargetOpts,PragmaList * Pragmas,llvm::raw_ostream * OS,Slang::OutputType OT,clang::SourceManager & SourceMgr,bool AllowRSPrefix,bool IsFilterscript)217 Backend::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 
Initialize(clang::ASTContext & Ctx)238 void 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.
WrapBitcode(llvm::raw_string_ostream & Bitcode)245 void 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 
HandleTranslationUnit(clang::ASTContext & Ctx)260 void 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 
HandleTagDeclDefinition(clang::TagDecl * D)396 void Backend::HandleTagDeclDefinition(clang::TagDecl *D) {
397   mGen->HandleTagDeclDefinition(D);
398 }
399 
CompleteTentativeDefinition(clang::VarDecl * D)400 void Backend::CompleteTentativeDefinition(clang::VarDecl *D) {
401   mGen->CompleteTentativeDefinition(D);
402 }
403 
~Backend()404 Backend::~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
AnnotateFunction(clang::FunctionDecl * FD)413 void 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 
HandleTopLevelDecl(clang::DeclGroupRef D)422 bool 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 
HandleTranslationUnitPre(clang::ASTContext & C)464 void 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 ///////////////////////////////////////////////////////////////////////////////
dumpExportVarInfo(llvm::Module * M)519 void 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 
dumpExportFunctionInfo(llvm::Module * M)604 void 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 
dumpExportForEachInfo(llvm::Module * M)744 void 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 
dumpExportTypeInfo(llvm::Module * M)781 void 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 
HandleTranslationUnitPost(llvm::Module * M)840 void 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