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