• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <iostream>
22 
23 #include "clang/AST/ASTContext.h"
24 #include "clang/AST/Attr.h"
25 #include "clang/AST/Decl.h"
26 #include "clang/AST/DeclGroup.h"
27 #include "clang/AST/RecordLayout.h"
28 
29 #include "clang/Basic/Diagnostic.h"
30 #include "clang/Basic/TargetInfo.h"
31 #include "clang/Basic/TargetOptions.h"
32 
33 #include "clang/CodeGen/ModuleBuilder.h"
34 
35 #include "clang/Frontend/CodeGenOptions.h"
36 #include "clang/Frontend/FrontendDiagnostic.h"
37 
38 #include "llvm/ADT/Twine.h"
39 #include "llvm/ADT/StringExtras.h"
40 
41 #include "llvm/Bitcode/ReaderWriter.h"
42 
43 #include "llvm/CodeGen/RegAllocRegistry.h"
44 #include "llvm/CodeGen/SchedulerRegistry.h"
45 
46 #include "llvm/IR/Constant.h"
47 #include "llvm/IR/Constants.h"
48 #include "llvm/IR/DataLayout.h"
49 #include "llvm/IR/DebugLoc.h"
50 #include "llvm/IR/DerivedTypes.h"
51 #include "llvm/IR/Function.h"
52 #include "llvm/IR/IRBuilder.h"
53 #include "llvm/IR/IRPrintingPasses.h"
54 #include "llvm/IR/LLVMContext.h"
55 #include "llvm/IR/Metadata.h"
56 #include "llvm/IR/Module.h"
57 
58 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
59 
60 #include "llvm/Target/TargetMachine.h"
61 #include "llvm/Target/TargetOptions.h"
62 #include "llvm/Support/TargetRegistry.h"
63 
64 #include "llvm/MC/SubtargetFeature.h"
65 
66 #include "slang_assert.h"
67 #include "slang.h"
68 #include "slang_bitcode_gen.h"
69 #include "slang_rs_context.h"
70 #include "slang_rs_export_foreach.h"
71 #include "slang_rs_export_func.h"
72 #include "slang_rs_export_reduce.h"
73 #include "slang_rs_export_type.h"
74 #include "slang_rs_export_var.h"
75 #include "slang_rs_metadata.h"
76 
77 #include "rs_cc_options.h"
78 
79 #include "StripUnkAttr/strip_unknown_attributes_pass.h"
80 
81 namespace {
82 class VersionInfoPass : public llvm::ModulePass {
83   const clang::CodeGenOptions &mCodeGenOpts;
84 
getSlangLLVMVersion() const85   const char *getSlangLLVMVersion() const {
86     if (mCodeGenOpts.getDebugInfo() != clang::codegenoptions::NoDebugInfo)
87       return LLVM_VERSION_STRING;
88     return nullptr;
89   }
90 
91 public:
92   static char ID;
VersionInfoPass(const clang::CodeGenOptions & codegenOpts)93   VersionInfoPass(const clang::CodeGenOptions &codegenOpts)
94       : ModulePass(ID), mCodeGenOpts(codegenOpts) {}
runOnModule(llvm::Module & M)95   virtual bool runOnModule(llvm::Module &M) override {
96     const char *versionString = getSlangLLVMVersion();
97     if (!versionString)
98       return false;
99     auto &ctx = M.getContext();
100     auto md = M.getOrInsertNamedMetadata("slang.llvm.version");
101     auto ver = llvm::MDString::get(ctx, versionString);
102     md->addOperand(
103         llvm::MDNode::get(ctx, llvm::ArrayRef<llvm::Metadata *>(ver)));
104     return true;
105   }
106 };
107 
108 char VersionInfoPass::ID = 0;
109 
createVersionInfoPass(const clang::CodeGenOptions & cgo)110 llvm::ModulePass *createVersionInfoPass(const clang::CodeGenOptions &cgo) {
111   return new VersionInfoPass(cgo);
112 }
113 }
114 
115 namespace slang {
116 
CreateFunctionPasses()117 void Backend::CreateFunctionPasses() {
118   if (!mPerFunctionPasses) {
119     mPerFunctionPasses = new llvm::legacy::FunctionPassManager(mpModule);
120 
121     llvm::PassManagerBuilder PMBuilder;
122     PMBuilder.OptLevel = mCodeGenOpts.OptimizationLevel;
123     PMBuilder.populateFunctionPassManager(*mPerFunctionPasses);
124   }
125 }
126 
CreateModulePasses()127 void Backend::CreateModulePasses() {
128   if (!mPerModulePasses) {
129     mPerModulePasses = new llvm::legacy::PassManager();
130 
131     llvm::PassManagerBuilder PMBuilder;
132     PMBuilder.OptLevel = mCodeGenOpts.OptimizationLevel;
133     PMBuilder.SizeLevel = mCodeGenOpts.OptimizeSize;
134     PMBuilder.DisableUnitAtATime = 0; // TODO Pirama confirm if this is right
135 
136     if (mCodeGenOpts.UnrollLoops) {
137       PMBuilder.DisableUnrollLoops = 0;
138     } else {
139       PMBuilder.DisableUnrollLoops = 1;
140     }
141 
142     PMBuilder.populateModulePassManager(*mPerModulePasses);
143     // Add a pass to strip off unknown/unsupported attributes.
144     mPerModulePasses->add(createStripUnknownAttributesPass());
145     if (!mContext->isCompatLib()) {
146       // The version info pass is used to ensure that debugging
147       // is matched between slang and bcc.
148       mPerModulePasses->add(createVersionInfoPass(mCodeGenOpts));
149     }
150   }
151 }
152 
CreateCodeGenPasses()153 bool Backend::CreateCodeGenPasses() {
154   if ((mOT != Slang::OT_Assembly) && (mOT != Slang::OT_Object))
155     return true;
156 
157   // Now we add passes for code emitting
158   if (mCodeGenPasses) {
159     return true;
160   } else {
161     mCodeGenPasses = new llvm::legacy::FunctionPassManager(mpModule);
162   }
163 
164   // Create the TargetMachine for generating code.
165   std::string Triple = mpModule->getTargetTriple();
166 
167   std::string Error;
168   const llvm::Target* TargetInfo =
169       llvm::TargetRegistry::lookupTarget(Triple, Error);
170   if (TargetInfo == nullptr) {
171     mDiagEngine.Report(clang::diag::err_fe_unable_to_create_target) << Error;
172     return false;
173   }
174 
175   // Target Machine Options
176   llvm::TargetOptions Options;
177 
178   // Use soft-float ABI for ARM (which is the target used by Slang during code
179   // generation).  Codegen still uses hardware FPU by default.  To use software
180   // floating point, add 'soft-float' feature to FeaturesStr below.
181   Options.FloatABIType = llvm::FloatABI::Soft;
182 
183   // BCC needs all unknown symbols resolved at compilation time. So we don't
184   // need any relocation model.
185   llvm::Reloc::Model RM = llvm::Reloc::Static;
186 
187   // This is set for the linker (specify how large of the virtual addresses we
188   // can access for all unknown symbols.)
189   llvm::CodeModel::Model CM;
190   if (mpModule->getDataLayout().getPointerSize() == 4) {
191     CM = llvm::CodeModel::Small;
192   } else {
193     // The target may have pointer size greater than 32 (e.g. x86_64
194     // architecture) may need large data address model
195     CM = llvm::CodeModel::Medium;
196   }
197 
198   // Setup feature string
199   std::string FeaturesStr;
200   if (mTargetOpts.CPU.size() || mTargetOpts.Features.size()) {
201     llvm::SubtargetFeatures Features;
202 
203     for (std::vector<std::string>::const_iterator
204              I = mTargetOpts.Features.begin(), E = mTargetOpts.Features.end();
205          I != E;
206          I++)
207       Features.AddFeature(*I);
208 
209     FeaturesStr = Features.getString();
210   }
211 
212   llvm::TargetMachine *TM =
213     TargetInfo->createTargetMachine(Triple, mTargetOpts.CPU, FeaturesStr,
214                                     Options, RM, CM);
215 
216   // Register allocation policy:
217   //  createFastRegisterAllocator: fast but bad quality
218   //  createGreedyRegisterAllocator: not so fast but good quality
219   llvm::RegisterRegAlloc::setDefault((mCodeGenOpts.OptimizationLevel == 0) ?
220                                      llvm::createFastRegisterAllocator :
221                                      llvm::createGreedyRegisterAllocator);
222 
223   llvm::CodeGenOpt::Level OptLevel = llvm::CodeGenOpt::Default;
224   if (mCodeGenOpts.OptimizationLevel == 0) {
225     OptLevel = llvm::CodeGenOpt::None;
226   } else if (mCodeGenOpts.OptimizationLevel == 3) {
227     OptLevel = llvm::CodeGenOpt::Aggressive;
228   }
229 
230   llvm::TargetMachine::CodeGenFileType CGFT =
231       llvm::TargetMachine::CGFT_AssemblyFile;
232   if (mOT == Slang::OT_Object) {
233     CGFT = llvm::TargetMachine::CGFT_ObjectFile;
234   }
235   if (TM->addPassesToEmitFile(*mCodeGenPasses, mBufferOutStream,
236                               CGFT, OptLevel)) {
237     mDiagEngine.Report(clang::diag::err_fe_unable_to_interface_with_target);
238     return false;
239   }
240 
241   return true;
242 }
243 
Backend(RSContext * Context,clang::DiagnosticsEngine * DiagEngine,const RSCCOptions & Opts,const clang::HeaderSearchOptions & HeaderSearchOpts,const clang::PreprocessorOptions & PreprocessorOpts,const clang::CodeGenOptions & CodeGenOpts,const clang::TargetOptions & TargetOpts,PragmaList * Pragmas,llvm::raw_ostream * OS,Slang::OutputType OT,clang::SourceManager & SourceMgr,bool AllowRSPrefix,bool IsFilterscript)244 Backend::Backend(RSContext *Context, clang::DiagnosticsEngine *DiagEngine,
245                  const RSCCOptions &Opts,
246                  const clang::HeaderSearchOptions &HeaderSearchOpts,
247                  const clang::PreprocessorOptions &PreprocessorOpts,
248                  const clang::CodeGenOptions &CodeGenOpts,
249                  const clang::TargetOptions &TargetOpts, PragmaList *Pragmas,
250                  llvm::raw_ostream *OS, Slang::OutputType OT,
251                  clang::SourceManager &SourceMgr, bool AllowRSPrefix,
252                  bool IsFilterscript)
253     : ASTConsumer(), mTargetOpts(TargetOpts), mpModule(nullptr), mpOS(OS),
254       mOT(OT), mGen(nullptr), mPerFunctionPasses(nullptr),
255       mPerModulePasses(nullptr), mCodeGenPasses(nullptr),
256       mBufferOutStream(*mpOS), mContext(Context),
257       mSourceMgr(SourceMgr), mASTPrint(Opts.mASTPrint), mAllowRSPrefix(AllowRSPrefix),
258       mIsFilterscript(IsFilterscript), mExportVarMetadata(nullptr),
259       mExportFuncMetadata(nullptr), mExportForEachNameMetadata(nullptr),
260       mExportForEachSignatureMetadata(nullptr),
261       mExportReduceMetadata(nullptr),
262       mExportTypeMetadata(nullptr), mRSObjectSlotsMetadata(nullptr),
263       mRefCount(mContext->getASTContext()),
264       mASTChecker(Context, Context->getTargetAPI(), IsFilterscript),
265       mForEachHandler(Context),
266       mLLVMContext(slang::getGlobalLLVMContext()), mDiagEngine(*DiagEngine),
267       mCodeGenOpts(CodeGenOpts), mPragmas(Pragmas) {
268   mGen = CreateLLVMCodeGen(mDiagEngine, "", HeaderSearchOpts, PreprocessorOpts,
269       mCodeGenOpts, mLLVMContext);
270 }
271 
Initialize(clang::ASTContext & Ctx)272 void Backend::Initialize(clang::ASTContext &Ctx) {
273   mGen->Initialize(Ctx);
274 
275   mpModule = mGen->GetModule();
276 }
277 
HandleTranslationUnit(clang::ASTContext & Ctx)278 void Backend::HandleTranslationUnit(clang::ASTContext &Ctx) {
279   HandleTranslationUnitPre(Ctx);
280 
281   if (mASTPrint)
282     Ctx.getTranslationUnitDecl()->dump();
283 
284   mGen->HandleTranslationUnit(Ctx);
285 
286   // Here, we complete a translation unit (whole translation unit is now in LLVM
287   // IR). Now, interact with LLVM backend to generate actual machine code (asm
288   // or machine code, whatever.)
289 
290   // Silently ignore if we weren't initialized for some reason.
291   if (!mpModule)
292     return;
293 
294   llvm::Module *M = mGen->ReleaseModule();
295   if (!M) {
296     // The module has been released by IR gen on failures, do not double free.
297     mpModule = nullptr;
298     return;
299   }
300 
301   slangAssert(mpModule == M &&
302               "Unexpected module change during LLVM IR generation");
303 
304   // Insert #pragma information into metadata section of module
305   if (!mPragmas->empty()) {
306     llvm::NamedMDNode *PragmaMetadata =
307         mpModule->getOrInsertNamedMetadata(Slang::PragmaMetadataName);
308     for (PragmaList::const_iterator I = mPragmas->begin(), E = mPragmas->end();
309          I != E;
310          I++) {
311       llvm::SmallVector<llvm::Metadata*, 2> Pragma;
312       // Name goes first
313       Pragma.push_back(llvm::MDString::get(mLLVMContext, I->first));
314       // And then value
315       Pragma.push_back(llvm::MDString::get(mLLVMContext, I->second));
316 
317       // Create MDNode and insert into PragmaMetadata
318       PragmaMetadata->addOperand(
319           llvm::MDNode::get(mLLVMContext, Pragma));
320     }
321   }
322 
323   HandleTranslationUnitPost(mpModule);
324 
325   // Create passes for optimization and code emission
326 
327   // Create and run per-function passes
328   CreateFunctionPasses();
329   if (mPerFunctionPasses) {
330     mPerFunctionPasses->doInitialization();
331 
332     for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end();
333          I != E;
334          I++)
335       if (!I->isDeclaration())
336         mPerFunctionPasses->run(*I);
337 
338     mPerFunctionPasses->doFinalization();
339   }
340 
341   // Create and run module passes
342   CreateModulePasses();
343   if (mPerModulePasses)
344     mPerModulePasses->run(*mpModule);
345 
346   switch (mOT) {
347     case Slang::OT_Assembly:
348     case Slang::OT_Object: {
349       if (!CreateCodeGenPasses())
350         return;
351 
352       mCodeGenPasses->doInitialization();
353 
354       for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end();
355           I != E;
356           I++)
357         if (!I->isDeclaration())
358           mCodeGenPasses->run(*I);
359 
360       mCodeGenPasses->doFinalization();
361       break;
362     }
363     case Slang::OT_LLVMAssembly: {
364       llvm::legacy::PassManager *LLEmitPM = new llvm::legacy::PassManager();
365       LLEmitPM->add(llvm::createPrintModulePass(mBufferOutStream));
366       LLEmitPM->run(*mpModule);
367       break;
368     }
369     case Slang::OT_Bitcode: {
370       writeBitcode(mBufferOutStream, *mpModule, getTargetAPI(),
371                    mCodeGenOpts.OptimizationLevel, mCodeGenOpts.getDebugInfo());
372       break;
373     }
374     case Slang::OT_Nothing: {
375       return;
376     }
377     default: {
378       slangAssert(false && "Unknown output type");
379     }
380   }
381 }
382 
383 // Insert explicit padding fields into struct to follow the current layout.
384 //
385 // A similar algorithm is present in PadHelperFunctionStruct().
PadStruct(clang::RecordDecl * RD)386 void Backend::PadStruct(clang::RecordDecl* RD) {
387   // Example of padding:
388   //
389   //   // ORIGINAL CODE                   // TRANSFORMED CODE
390   //   struct foo {                       struct foo {
391   //     int a;                             int a;
392   //     // 4 bytes of padding              char <RS_PADDING_FIELD_NAME>[4];
393   //     long b;                            long b;
394   //     int c;                             int c;
395   //     // 4 bytes of (tail) padding       char <RS_PADDING_FIELD_NAME>[4];
396   //   };                                 };
397 
398   // We collect all of RD's fields in a vector FieldsInfo.  We
399   // represent tail padding as an entry in the FieldsInfo vector with a
400   // null FieldDecl.
401   typedef std::pair<size_t, clang::FieldDecl*> FieldInfoType;  // (pre-field padding bytes, field)
402   std::vector<FieldInfoType> FieldsInfo;
403 
404   // RenderScript is C99-based, so we only expect to see fields.  We
405   // could iterate over fields, but instead let's iterate over
406   // everything, to verify that there are only fields.
407   for (clang::Decl* D : RD->decls()) {
408     clang::FieldDecl* FD = clang::dyn_cast<clang::FieldDecl>(D);
409     slangAssert(FD && "found a non field declaration within a struct");
410     FieldsInfo.push_back(std::make_pair(size_t(0), FD));
411   }
412 
413   clang::ASTContext& ASTC = mContext->getASTContext();
414 
415   // ASTContext caches record layout.  We may transform the record in a way
416   // that would render this cached information incorrect.  clang does
417   // not provide any way to invalidate this cached information.  We
418   // take the following approach:
419   //
420   // 1. ASSUME that record layout has not yet been computed for RD.
421   //
422   // 2. Create a temporary clone of RD, and compute its layout.
423   //    ASSUME that we know how to clone RD in a way that copies all the
424   //    properties that are relevant to its layout.
425   //
426   // 3. Use the layout information from the temporary clone to
427   //    transform RD.
428   //
429   // NOTE: ASTContext also caches TypeInfo (see
430   //       ASTContext::getTypeInfo()).  ASSUME that inserting padding
431   //       fields doesn't change the type in any way that affects
432   //       TypeInfo.
433   //
434   // NOTE: A RecordType knows its associated RecordDecl -- so even
435   //       while we're manipulating RD, the associated RecordType
436   //       still recognizes RD as its RecordDecl.  ASSUME that we
437   //       don't do anything during our manipulation that would cause
438   //       the RecordType to be followed to RD while RD is in a
439   //       partially transformed state.
440 
441   // The assumptions above may be brittle, and if they are incorrect,
442   // we may get mysterious failures.
443 
444   // create a temporary clone
445   clang::RecordDecl* RDForLayout =
446       clang::RecordDecl::Create(ASTC, clang::TTK_Struct, RD->getDeclContext(),
447                                 clang::SourceLocation(), clang::SourceLocation(),
448                                 nullptr /* IdentifierInfo */);
449   RDForLayout->startDefinition();
450   RDForLayout->setTypeForDecl(RD->getTypeForDecl());
451   if (RD->hasAttrs())
452     RDForLayout->setAttrs(RD->getAttrs());
453   RDForLayout->completeDefinition();
454 
455   // move all fields from RD to RDForLayout
456   for (const auto &info : FieldsInfo) {
457     RD->removeDecl(info.second);
458     info.second->setLexicalDeclContext(RDForLayout);
459     RDForLayout->addDecl(info.second);
460   }
461 
462   const clang::ASTRecordLayout& RL = ASTC.getASTRecordLayout(RDForLayout);
463 
464   // An exportable type cannot contain a bitfield.  However, it's
465   // possible that this current type might have a bitfield and yet
466   // share a common initial sequence with an exportable type, so even
467   // if the current type has a bitfield, the current type still
468   // needs to have explicit padding inserted (in case the two types
469   // under discussion are members of a union).  We don't need to
470   // insert any padding after the bitfield, however, because that
471   // would be beyond the common initial sequence.
472   bool foundBitField = false;
473 
474   // Is there any padding in this struct?
475   bool foundPadding = false;
476 
477   unsigned fieldNo = 0;
478   uint64_t fieldPrePaddingOffset = 0;  // byte offset of pre-field padding within struct
479   for (auto &info : FieldsInfo) {
480     const clang::FieldDecl* FD = info.second;
481 
482     if ((foundBitField = FD->isBitField()))
483       break;
484 
485     const uint64_t fieldOffset = RL.getFieldOffset(fieldNo) >> 3;
486     const size_t prePadding = fieldOffset - fieldPrePaddingOffset;
487     foundPadding |= (prePadding != 0);
488     info.first = prePadding;
489 
490     // get ready for the next field
491     //
492     //   assumes that getTypeSize() is the storage size of the Type -- for example,
493     //   that it includes a struct's tail padding (if any)
494     //
495     fieldPrePaddingOffset = fieldOffset + (ASTC.getTypeSize(FD->getType()) >> 3);
496     ++fieldNo;
497   }
498 
499   if (!foundBitField) {
500     // In order to ensure that the front end (including reflected
501     // code) and back end agree on struct size (not just field
502     // offsets) we may need to add explicit tail padding, just as we'e
503     // added explicit padding between fields.
504     slangAssert(RL.getSize().getQuantity() >= fieldPrePaddingOffset);
505     if (const size_t tailPadding = RL.getSize().getQuantity() - fieldPrePaddingOffset) {
506       foundPadding = true;
507       FieldsInfo.push_back(std::make_pair(tailPadding, nullptr));
508     }
509   }
510 
511   if (false /* change to "true" for extra debugging output */) {
512    if (foundPadding) {
513      std::cout << "PadStruct(" << RD->getNameAsString() << "):" << std::endl;
514      for (const auto &info : FieldsInfo)
515        std::cout << "  " << info.first << ", " << (info.second ? info.second->getNameAsString() : "<tail>") << std::endl;
516    }
517   }
518 
519   if (foundPadding && Slang::IsLocInRSHeaderFile(RD->getLocation(), mSourceMgr)) {
520     mContext->ReportError(RD->getLocation(), "system structure contains padding: '%0'")
521         << RD->getName();
522   }
523 
524   // now move fields from RDForLayout to RD, and add any necessary
525   // padding fields
526   const clang::QualType byteType = ASTC.getIntTypeForBitwidth(8, false /* not signed */);
527   clang::IdentifierInfo* const paddingIdentifierInfo = &ASTC.Idents.get(RS_PADDING_FIELD_NAME);
528   for (const auto &info : FieldsInfo) {
529     if (info.first != 0) {
530       // Create a padding field: "char <RS_PADDING_FIELD_NAME>[<info.first>];"
531 
532       // TODO: Do we need to do anything else to keep this field from being shown in debugger?
533       //       There's no source location, and the field is marked as implicit.
534       const clang::QualType paddingType =
535           ASTC.getConstantArrayType(byteType,
536                                     llvm::APInt(sizeof(info.first) << 3, info.first),
537                                     clang::ArrayType::Normal, 0 /* IndexTypeQuals */);
538       clang::FieldDecl* const FD =
539           clang::FieldDecl::Create(ASTC, RD, clang::SourceLocation(), clang::SourceLocation(),
540                                    paddingIdentifierInfo,
541                                    paddingType,
542                                    nullptr,  // TypeSourceInfo*
543                                    nullptr,  // BW (bitwidth)
544                                    false,    // Mutable = false
545                                    clang::ICIS_NoInit);
546       FD->setImplicit(true);
547       RD->addDecl(FD);
548     }
549     if (info.second != nullptr) {
550       RDForLayout->removeDecl(info.second);
551       info.second->setLexicalDeclContext(RD);
552       RD->addDecl(info.second);
553     }
554   }
555 
556   // There does not appear to be any safe way to delete a RecordDecl
557   // -- for example, there is no RecordDecl destructor to invalidate
558   // cached record layout, and if we were to get unlucky, some future
559   // RecordDecl could be allocated in the same place as a deleted
560   // RDForLayout and "inherit" the cached record layout from
561   // RDForLayout.
562 }
563 
HandleTagDeclDefinition(clang::TagDecl * D)564 void Backend::HandleTagDeclDefinition(clang::TagDecl *D) {
565   // we want to insert explicit padding fields into structs per http://b/29154200 and http://b/28070272
566   switch (D->getTagKind()) {
567     case clang::TTK_Struct:
568       PadStruct(llvm::cast<clang::RecordDecl>(D));
569       break;
570 
571     case clang::TTK_Union:
572       // cannot be part of an exported type
573       break;
574 
575     case clang::TTK_Enum:
576       // a scalar
577       break;
578 
579     case clang::TTK_Class:
580     case clang::TTK_Interface:
581     default:
582       slangAssert(false && "Unexpected TagTypeKind");
583       break;
584   }
585   mGen->HandleTagDeclDefinition(D);
586 }
587 
CompleteTentativeDefinition(clang::VarDecl * D)588 void Backend::CompleteTentativeDefinition(clang::VarDecl *D) {
589   mGen->CompleteTentativeDefinition(D);
590 }
591 
~Backend()592 Backend::~Backend() {
593   delete mpModule;
594   delete mGen;
595   delete mPerFunctionPasses;
596   delete mPerModulePasses;
597   delete mCodeGenPasses;
598 }
599 
600 // 1) Add zero initialization of local RS object types
AnnotateFunction(clang::FunctionDecl * FD)601 void Backend::AnnotateFunction(clang::FunctionDecl *FD) {
602   if (FD &&
603       FD->hasBody() &&
604       !FD->isImplicit() &&
605       !Slang::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr)) {
606     mRefCount.Init();
607     mRefCount.SetDeclContext(FD);
608     mRefCount.HandleParamsAndLocals(FD);
609   }
610 }
611 
HandleTopLevelDecl(clang::DeclGroupRef D)612 bool Backend::HandleTopLevelDecl(clang::DeclGroupRef D) {
613   // Find and remember the types for rs_allocation and rs_script_call_t so
614   // they can be used later for translating rsForEach() calls.
615   for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end();
616        (mContext->getAllocationType().isNull() ||
617         mContext->getScriptCallType().isNull()) &&
618        I != E; I++) {
619     if (clang::TypeDecl* TD = llvm::dyn_cast<clang::TypeDecl>(*I)) {
620       clang::StringRef TypeName = TD->getName();
621       if (TypeName.equals("rs_allocation")) {
622         mContext->setAllocationType(TD);
623       } else if (TypeName.equals("rs_script_call_t")) {
624         mContext->setScriptCallType(TD);
625       }
626     }
627   }
628 
629   // Disallow user-defined functions with prefix "rs"
630   if (!mAllowRSPrefix) {
631     // Iterate all function declarations in the program.
632     for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end();
633          I != E; I++) {
634       clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
635       if (FD == nullptr)
636         continue;
637       if (!FD->getName().startswith("rs"))  // Check prefix
638         continue;
639       if (!Slang::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr))
640         mContext->ReportError(FD->getLocation(),
641                               "invalid function name prefix, "
642                               "\"rs\" is reserved: '%0'")
643             << FD->getName();
644     }
645   }
646 
647   for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; I++) {
648     clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
649     if (FD) {
650       // Handle forward reference from pragma (see
651       // RSReducePragmaHandler::HandlePragma for backward reference).
652       mContext->markUsedByReducePragma(FD, RSContext::CheckNameYes);
653       if (FD->isGlobal()) {
654         // Check that we don't have any array parameters being misinterpreted as
655         // kernel pointers due to the C type system's array to pointer decay.
656         size_t numParams = FD->getNumParams();
657         for (size_t i = 0; i < numParams; i++) {
658           const clang::ParmVarDecl *PVD = FD->getParamDecl(i);
659           clang::QualType QT = PVD->getOriginalType();
660           if (QT->isArrayType()) {
661             mContext->ReportError(
662                 PVD->getTypeSpecStartLoc(),
663                 "exported function parameters may not have array type: %0")
664                 << QT;
665           }
666         }
667         AnnotateFunction(FD);
668       }
669     }
670 
671     if (getTargetAPI() >= SLANG_FEATURE_SINGLE_SOURCE_API) {
672       if (FD && FD->hasBody() && !FD->isImplicit() &&
673           !Slang::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr)) {
674         if (FD->hasAttr<clang::RenderScriptKernelAttr>()) {
675           // Log functions with attribute "kernel" by their names, and assign
676           // them slot numbers. Any other function cannot be used in a
677           // rsForEach() or rsForEachWithOptions() call, including old-style
678           // kernel functions which are defined without the "kernel" attribute.
679           mContext->addForEach(FD);
680         }
681         // Look for any kernel launch calls and translate them into using the
682         // internal API.
683         // Report a compiler error on kernel launches inside a kernel.
684         mForEachHandler.handleForEachCalls(FD, getTargetAPI());
685       }
686     }
687   }
688 
689   return mGen->HandleTopLevelDecl(D);
690 }
691 
HandleTranslationUnitPre(clang::ASTContext & C)692 void Backend::HandleTranslationUnitPre(clang::ASTContext &C) {
693   clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
694 
695   if (!mContext->processReducePragmas(this))
696     return;
697 
698   // If we have an invalid RS/FS AST, don't check further.
699   if (!mASTChecker.Validate()) {
700     return;
701   }
702 
703   if (mIsFilterscript) {
704     mContext->addPragma("rs_fp_relaxed", "");
705   }
706 
707   int version = mContext->getVersion();
708   if (version == 0) {
709     // Not setting a version is an error
710     mDiagEngine.Report(
711         mSourceMgr.getLocForEndOfFile(mSourceMgr.getMainFileID()),
712         mDiagEngine.getCustomDiagID(
713             clang::DiagnosticsEngine::Error,
714             "missing pragma for version in source file"));
715   } else {
716     slangAssert(version == 1);
717   }
718 
719   if (mContext->getReflectJavaPackageName().empty()) {
720     mDiagEngine.Report(
721         mSourceMgr.getLocForEndOfFile(mSourceMgr.getMainFileID()),
722         mDiagEngine.getCustomDiagID(clang::DiagnosticsEngine::Error,
723                                     "missing \"#pragma rs "
724                                     "java_package_name(com.foo.bar)\" "
725                                     "in source file"));
726     return;
727   }
728 
729   // Create a static global destructor if necessary (to handle RS object
730   // runtime cleanup).
731   clang::FunctionDecl *FD = mRefCount.CreateStaticGlobalDtor();
732   if (FD) {
733     HandleTopLevelDecl(clang::DeclGroupRef(FD));
734   }
735 
736   // Process any static function declarations
737   for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
738           E = TUDecl->decls_end(); I != E; I++) {
739     if ((I->getKind() >= clang::Decl::firstFunction) &&
740         (I->getKind() <= clang::Decl::lastFunction)) {
741       clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
742       if (FD && !FD->isGlobal()) {
743         AnnotateFunction(FD);
744       }
745     }
746   }
747 }
748 
749 ///////////////////////////////////////////////////////////////////////////////
dumpExportVarInfo(llvm::Module * M)750 void Backend::dumpExportVarInfo(llvm::Module *M) {
751   int slotCount = 0;
752   if (mExportVarMetadata == nullptr)
753     mExportVarMetadata = M->getOrInsertNamedMetadata(RS_EXPORT_VAR_MN);
754 
755   llvm::SmallVector<llvm::Metadata *, 2> ExportVarInfo;
756 
757   // We emit slot information (#rs_object_slots) for any reference counted
758   // RS type or pointer (which can also be bound).
759 
760   for (RSContext::const_export_var_iterator I = mContext->export_vars_begin(),
761           E = mContext->export_vars_end();
762        I != E;
763        I++) {
764     const RSExportVar *EV = *I;
765     const RSExportType *ET = EV->getType();
766     bool countsAsRSObject = false;
767 
768     // Variable name
769     ExportVarInfo.push_back(
770         llvm::MDString::get(mLLVMContext, EV->getName().c_str()));
771 
772     // Type name
773     switch (ET->getClass()) {
774       case RSExportType::ExportClassPrimitive: {
775         const RSExportPrimitiveType *PT =
776             static_cast<const RSExportPrimitiveType*>(ET);
777         ExportVarInfo.push_back(
778             llvm::MDString::get(
779               mLLVMContext, llvm::utostr(PT->getType())));
780         if (PT->isRSObjectType()) {
781           countsAsRSObject = true;
782         }
783         break;
784       }
785       case RSExportType::ExportClassPointer: {
786         ExportVarInfo.push_back(
787             llvm::MDString::get(
788               mLLVMContext, ("*" + static_cast<const RSExportPointerType*>(ET)
789                 ->getPointeeType()->getName()).c_str()));
790         break;
791       }
792       case RSExportType::ExportClassMatrix: {
793         ExportVarInfo.push_back(
794             llvm::MDString::get(
795               mLLVMContext, llvm::utostr(
796                   /* TODO Strange value.  This pushes just a number, quite
797                    * different than the other cases.  What is this used for?
798                    * These are the metadata values that some partner drivers
799                    * want to reference (for TBAA, etc.). We may want to look
800                    * at whether these provide any reasonable value (or have
801                    * distinct enough values to actually depend on).
802                    */
803                 DataTypeRSMatrix2x2 +
804                 static_cast<const RSExportMatrixType*>(ET)->getDim() - 2)));
805         break;
806       }
807       case RSExportType::ExportClassVector:
808       case RSExportType::ExportClassConstantArray:
809       case RSExportType::ExportClassRecord: {
810         ExportVarInfo.push_back(
811             llvm::MDString::get(mLLVMContext,
812               EV->getType()->getName().c_str()));
813         break;
814       }
815     }
816 
817     mExportVarMetadata->addOperand(
818         llvm::MDNode::get(mLLVMContext, ExportVarInfo));
819     ExportVarInfo.clear();
820 
821     if (mRSObjectSlotsMetadata == nullptr) {
822       mRSObjectSlotsMetadata =
823           M->getOrInsertNamedMetadata(RS_OBJECT_SLOTS_MN);
824     }
825 
826     if (countsAsRSObject) {
827       mRSObjectSlotsMetadata->addOperand(llvm::MDNode::get(mLLVMContext,
828           llvm::MDString::get(mLLVMContext, llvm::utostr(slotCount))));
829     }
830 
831     slotCount++;
832   }
833 }
834 
835 // A similar algorithm is present in Backend::PadStruct().
PadHelperFunctionStruct(llvm::Module * M,llvm::StructType ** paddedStructType,std::vector<unsigned> * origFieldNumToPaddedFieldNum,llvm::StructType * origStructType)836 static void PadHelperFunctionStruct(llvm::Module *M,
837                                     llvm::StructType **paddedStructType,
838                                     std::vector<unsigned> *origFieldNumToPaddedFieldNum,
839                                     llvm::StructType *origStructType) {
840   slangAssert(origFieldNumToPaddedFieldNum->empty());
841   origFieldNumToPaddedFieldNum->resize(2 * origStructType->getNumElements());
842 
843   llvm::LLVMContext &llvmContext = M->getContext();
844 
845   const llvm::DataLayout *DL = &M->getDataLayout();
846   const llvm::StructLayout *SL = DL->getStructLayout(origStructType);
847 
848   // Field types -- including any padding fields we need to insert.
849   std::vector<llvm::Type *> paddedFieldTypes;
850   paddedFieldTypes.reserve(2 * origStructType->getNumElements());
851 
852   // Is there any padding in this struct?
853   bool foundPadding = false;
854 
855   llvm::Type *const byteType = llvm::Type::getInt8Ty(llvmContext);
856   unsigned origFieldNum = 0, paddedFieldNum = 0;
857   uint64_t fieldPrePaddingOffset = 0;  // byte offset of pre-field padding within struct
858   for (llvm::Type *fieldType : origStructType->elements()) {
859     const uint64_t fieldOffset = SL->getElementOffset(origFieldNum);
860     const size_t prePadding = fieldOffset - fieldPrePaddingOffset;
861     if (prePadding != 0) {
862       foundPadding = true;
863       paddedFieldTypes.push_back(llvm::ArrayType::get(byteType, prePadding));
864       ++paddedFieldNum;
865     }
866     paddedFieldTypes.push_back(fieldType);
867     (*origFieldNumToPaddedFieldNum)[origFieldNum] = paddedFieldNum;
868 
869     // get ready for the next field
870     fieldPrePaddingOffset = fieldOffset + DL->getTypeAllocSize(fieldType);
871     ++origFieldNum;
872     ++paddedFieldNum;
873   }
874 
875   // In order to ensure that the front end (including reflected code)
876   // and back end agree on struct size (not just field offsets) we may
877   // need to add explicit tail padding, just as we'e added explicit
878   // padding between fields.
879   slangAssert(SL->getSizeInBytes() >= fieldPrePaddingOffset);
880   if (const size_t tailPadding = SL->getSizeInBytes() - fieldPrePaddingOffset) {
881     foundPadding = true;
882     paddedFieldTypes.push_back(llvm::ArrayType::get(byteType, tailPadding));
883   }
884 
885   *paddedStructType = (foundPadding
886                        ? llvm::StructType::get(llvmContext, paddedFieldTypes)
887                        : origStructType);
888 }
889 
dumpExportFunctionInfo(llvm::Module * M)890 void Backend::dumpExportFunctionInfo(llvm::Module *M) {
891   if (mExportFuncMetadata == nullptr)
892     mExportFuncMetadata =
893         M->getOrInsertNamedMetadata(RS_EXPORT_FUNC_MN);
894 
895   llvm::SmallVector<llvm::Metadata *, 1> ExportFuncInfo;
896 
897   for (RSContext::const_export_func_iterator
898           I = mContext->export_funcs_begin(),
899           E = mContext->export_funcs_end();
900        I != E;
901        I++) {
902     const RSExportFunc *EF = *I;
903 
904     // Function name
905     if (!EF->hasParam()) {
906       ExportFuncInfo.push_back(llvm::MDString::get(mLLVMContext,
907                                                    EF->getName().c_str()));
908     } else {
909       llvm::Function *F = M->getFunction(EF->getName());
910       llvm::Function *HelperFunction;
911       const std::string HelperFunctionName(".helper_" + EF->getName());
912 
913       slangAssert(F && "Function marked as exported disappeared in Bitcode");
914 
915       // Create helper function
916       {
917         llvm::StructType *OrigHelperFunctionParameterTy = nullptr;
918         llvm::StructType *PaddedHelperFunctionParameterTy = nullptr;
919 
920         std::vector<unsigned> OrigFieldNumToPaddedFieldNum;
921         std::vector<bool> isPassedViaPtr;
922 
923         if (!F->getArgumentList().empty()) {
924           std::vector<llvm::Type*> HelperFunctionParameterTys;
925           for (llvm::Function::arg_iterator AI = F->arg_begin(),
926                                             AE = F->arg_end();
927                AI != AE; AI++) {
928             if (AI->getType()->isPointerTy() &&
929                 AI->getType()->getPointerElementType()->isStructTy()) {
930               HelperFunctionParameterTys.push_back(
931                   AI->getType()->getPointerElementType());
932               isPassedViaPtr.push_back(true);
933             } else {
934               // on 64-bit architecture(s), a vector type could be too big
935               // to be passed in a register and instead passed
936               // via a pointer to a temporary copy
937               llvm::Type *Ty = AI->getType();
938               bool viaPtr = false;
939               if (Ty->isPointerTy() && Ty->getPointerElementType()) {
940                 Ty = Ty->getPointerElementType();
941                 viaPtr = true;
942               }
943               HelperFunctionParameterTys.push_back(Ty);
944               isPassedViaPtr.push_back(viaPtr);
945             }
946           }
947           OrigHelperFunctionParameterTy =
948               llvm::StructType::get(mLLVMContext, HelperFunctionParameterTys);
949           PadHelperFunctionStruct(M,
950                                   &PaddedHelperFunctionParameterTy, &OrigFieldNumToPaddedFieldNum,
951                                   OrigHelperFunctionParameterTy);
952         }
953 
954         if (!EF->checkParameterPacketType(OrigHelperFunctionParameterTy)) {
955           fprintf(stderr, "Failed to export function %s: parameter type "
956                           "mismatch during creation of helper function.\n",
957                   EF->getName().c_str());
958 
959           const RSExportRecordType *Expected = EF->getParamPacketType();
960           if (Expected) {
961             fprintf(stderr, "Expected:\n");
962             Expected->getLLVMType()->dump();
963           }
964           if (OrigHelperFunctionParameterTy) {
965             fprintf(stderr, "Got:\n");
966             OrigHelperFunctionParameterTy->dump();
967           }
968           abort();
969         }
970 
971         std::vector<llvm::Type*> Params;
972         if (PaddedHelperFunctionParameterTy) {
973           llvm::PointerType *HelperFunctionParameterTyP =
974               llvm::PointerType::getUnqual(PaddedHelperFunctionParameterTy);
975           Params.push_back(HelperFunctionParameterTyP);
976         }
977 
978         llvm::FunctionType * HelperFunctionType =
979             llvm::FunctionType::get(F->getReturnType(),
980                                     Params,
981                                     /* IsVarArgs = */false);
982 
983         HelperFunction =
984             llvm::Function::Create(HelperFunctionType,
985                                    llvm::GlobalValue::ExternalLinkage,
986                                    HelperFunctionName,
987                                    M);
988 
989         HelperFunction->addFnAttr(llvm::Attribute::NoInline);
990         HelperFunction->setCallingConv(F->getCallingConv());
991 
992         // Create helper function body
993         {
994           llvm::Argument *HelperFunctionParameter =
995               &(*HelperFunction->arg_begin());
996           llvm::BasicBlock *BB =
997               llvm::BasicBlock::Create(mLLVMContext, "entry", HelperFunction);
998           llvm::IRBuilder<> *IB = new llvm::IRBuilder<>(BB);
999           llvm::SmallVector<llvm::Value*, 6> Params;
1000           llvm::Value *Idx[2];
1001 
1002           Idx[0] =
1003               llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), 0);
1004 
1005           // getelementptr and load instruction for all elements in
1006           // parameter .p
1007           for (size_t origFieldNum = 0; origFieldNum < EF->getNumParameters(); origFieldNum++) {
1008             // getelementptr
1009             Idx[1] = llvm::ConstantInt::get(
1010               llvm::Type::getInt32Ty(mLLVMContext), OrigFieldNumToPaddedFieldNum[origFieldNum]);
1011 
1012             llvm::Value *Ptr = NULL;
1013 
1014             Ptr = IB->CreateInBoundsGEP(HelperFunctionParameter, Idx);
1015 
1016             // Load is only required for non-struct ptrs
1017             if (isPassedViaPtr[origFieldNum]) {
1018                 Params.push_back(Ptr);
1019             } else {
1020                 llvm::Value *V = IB->CreateLoad(Ptr);
1021                 Params.push_back(V);
1022             }
1023           }
1024 
1025           // Call and pass the all elements as parameter to F
1026           llvm::CallInst *CI = IB->CreateCall(F, Params);
1027 
1028           CI->setCallingConv(F->getCallingConv());
1029 
1030           if (F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext)) {
1031             IB->CreateRetVoid();
1032           } else {
1033             IB->CreateRet(CI);
1034           }
1035 
1036           delete IB;
1037         }
1038       }
1039 
1040       ExportFuncInfo.push_back(
1041           llvm::MDString::get(mLLVMContext, HelperFunctionName.c_str()));
1042     }
1043 
1044     mExportFuncMetadata->addOperand(
1045         llvm::MDNode::get(mLLVMContext, ExportFuncInfo));
1046     ExportFuncInfo.clear();
1047   }
1048 }
1049 
dumpExportForEachInfo(llvm::Module * M)1050 void Backend::dumpExportForEachInfo(llvm::Module *M) {
1051   if (mExportForEachNameMetadata == nullptr) {
1052     mExportForEachNameMetadata =
1053         M->getOrInsertNamedMetadata(RS_EXPORT_FOREACH_NAME_MN);
1054   }
1055   if (mExportForEachSignatureMetadata == nullptr) {
1056     mExportForEachSignatureMetadata =
1057         M->getOrInsertNamedMetadata(RS_EXPORT_FOREACH_MN);
1058   }
1059 
1060   llvm::SmallVector<llvm::Metadata *, 1> ExportForEachName;
1061   llvm::SmallVector<llvm::Metadata *, 1> ExportForEachInfo;
1062 
1063   for (RSContext::const_export_foreach_iterator
1064           I = mContext->export_foreach_begin(),
1065           E = mContext->export_foreach_end();
1066        I != E;
1067        I++) {
1068     const RSExportForEach *EFE = *I;
1069 
1070     ExportForEachName.push_back(
1071         llvm::MDString::get(mLLVMContext, EFE->getName().c_str()));
1072 
1073     mExportForEachNameMetadata->addOperand(
1074         llvm::MDNode::get(mLLVMContext, ExportForEachName));
1075     ExportForEachName.clear();
1076 
1077     ExportForEachInfo.push_back(
1078         llvm::MDString::get(mLLVMContext,
1079                             llvm::utostr(EFE->getSignatureMetadata())));
1080 
1081     mExportForEachSignatureMetadata->addOperand(
1082         llvm::MDNode::get(mLLVMContext, ExportForEachInfo));
1083     ExportForEachInfo.clear();
1084   }
1085 }
1086 
dumpExportReduceInfo(llvm::Module * M)1087 void Backend::dumpExportReduceInfo(llvm::Module *M) {
1088   if (!mExportReduceMetadata) {
1089     mExportReduceMetadata =
1090       M->getOrInsertNamedMetadata(RS_EXPORT_REDUCE_MN);
1091   }
1092 
1093   llvm::SmallVector<llvm::Metadata *, 6> ExportReduceInfo;
1094   // Add operand to ExportReduceInfo, padding out missing operands with
1095   // nullptr.
1096   auto addOperand = [&ExportReduceInfo](uint32_t Idx, llvm::Metadata *N) {
1097     while (Idx > ExportReduceInfo.size())
1098       ExportReduceInfo.push_back(nullptr);
1099     ExportReduceInfo.push_back(N);
1100   };
1101   // Add string operand to ExportReduceInfo, padding out missing operands
1102   // with nullptr.
1103   // If string is empty, then do not add it unless Always is true.
1104   auto addString = [&addOperand, this](uint32_t Idx, const std::string &S,
1105                                        bool Always = true) {
1106     if (Always || !S.empty())
1107       addOperand(Idx, llvm::MDString::get(mLLVMContext, S));
1108   };
1109 
1110   // Add the description of the reduction kernels to the metadata node.
1111   for (auto I = mContext->export_reduce_begin(),
1112             E = mContext->export_reduce_end();
1113        I != E; ++I) {
1114     ExportReduceInfo.clear();
1115 
1116     int Idx = 0;
1117 
1118     addString(Idx++, (*I)->getNameReduce());
1119 
1120     addOperand(Idx++, llvm::MDString::get(mLLVMContext, llvm::utostr((*I)->getAccumulatorTypeSize())));
1121 
1122     llvm::SmallVector<llvm::Metadata *, 2> Accumulator;
1123     Accumulator.push_back(
1124       llvm::MDString::get(mLLVMContext, (*I)->getNameAccumulator()));
1125     Accumulator.push_back(llvm::MDString::get(
1126       mLLVMContext,
1127       llvm::utostr((*I)->getAccumulatorSignatureMetadata())));
1128     addOperand(Idx++, llvm::MDTuple::get(mLLVMContext, Accumulator));
1129 
1130     addString(Idx++, (*I)->getNameInitializer(), false);
1131     addString(Idx++, (*I)->getNameCombiner(), false);
1132     addString(Idx++, (*I)->getNameOutConverter(), false);
1133     addString(Idx++, (*I)->getNameHalter(), false);
1134 
1135     mExportReduceMetadata->addOperand(
1136       llvm::MDTuple::get(mLLVMContext, ExportReduceInfo));
1137   }
1138 }
1139 
dumpExportTypeInfo(llvm::Module * M)1140 void Backend::dumpExportTypeInfo(llvm::Module *M) {
1141   llvm::SmallVector<llvm::Metadata *, 1> ExportTypeInfo;
1142 
1143   for (RSContext::const_export_type_iterator
1144           I = mContext->export_types_begin(),
1145           E = mContext->export_types_end();
1146        I != E;
1147        I++) {
1148     // First, dump type name list to export
1149     const RSExportType *ET = I->getValue();
1150 
1151     ExportTypeInfo.clear();
1152     // Type name
1153     ExportTypeInfo.push_back(
1154         llvm::MDString::get(mLLVMContext, ET->getName().c_str()));
1155 
1156     if (ET->getClass() == RSExportType::ExportClassRecord) {
1157       const RSExportRecordType *ERT =
1158           static_cast<const RSExportRecordType*>(ET);
1159 
1160       if (mExportTypeMetadata == nullptr)
1161         mExportTypeMetadata =
1162             M->getOrInsertNamedMetadata(RS_EXPORT_TYPE_MN);
1163 
1164       mExportTypeMetadata->addOperand(
1165           llvm::MDNode::get(mLLVMContext, ExportTypeInfo));
1166 
1167       // Now, export struct field information to %[struct name]
1168       std::string StructInfoMetadataName("%");
1169       StructInfoMetadataName.append(ET->getName());
1170       llvm::NamedMDNode *StructInfoMetadata =
1171           M->getOrInsertNamedMetadata(StructInfoMetadataName);
1172       llvm::SmallVector<llvm::Metadata *, 3> FieldInfo;
1173 
1174       slangAssert(StructInfoMetadata->getNumOperands() == 0 &&
1175                   "Metadata with same name was created before");
1176       for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
1177               FE = ERT->fields_end();
1178            FI != FE;
1179            FI++) {
1180         const RSExportRecordType::Field *F = *FI;
1181 
1182         // 1. field name
1183         FieldInfo.push_back(llvm::MDString::get(mLLVMContext,
1184                                                 F->getName().c_str()));
1185 
1186         // 2. field type name
1187         FieldInfo.push_back(
1188             llvm::MDString::get(mLLVMContext,
1189                                 F->getType()->getName().c_str()));
1190 
1191         StructInfoMetadata->addOperand(
1192             llvm::MDNode::get(mLLVMContext, FieldInfo));
1193         FieldInfo.clear();
1194       }
1195     }   // ET->getClass() == RSExportType::ExportClassRecord
1196   }
1197 }
1198 
HandleTranslationUnitPost(llvm::Module * M)1199 void Backend::HandleTranslationUnitPost(llvm::Module *M) {
1200 
1201   if (!mContext->is64Bit()) {
1202     M->setDataLayout("e-p:32:32-i64:64-v128:64:128-n32-S64");
1203   }
1204 
1205   if (!mContext->processExports())
1206     return;
1207 
1208   if (mContext->hasExportVar())
1209     dumpExportVarInfo(M);
1210 
1211   if (mContext->hasExportFunc())
1212     dumpExportFunctionInfo(M);
1213 
1214   if (mContext->hasExportForEach())
1215     dumpExportForEachInfo(M);
1216 
1217   if (mContext->hasExportReduce())
1218     dumpExportReduceInfo(M);
1219 
1220   if (mContext->hasExportType())
1221     dumpExportTypeInfo(M);
1222 }
1223 
1224 }  // namespace slang
1225