1 /*
2 * Copyright 2010-2012, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "slang_backend.h"
18
19 #include <string>
20 #include <vector>
21
22 #include "clang/AST/ASTContext.h"
23 #include "clang/AST/Attr.h"
24 #include "clang/AST/Decl.h"
25 #include "clang/AST/DeclGroup.h"
26
27 #include "clang/Basic/Diagnostic.h"
28 #include "clang/Basic/TargetInfo.h"
29 #include "clang/Basic/TargetOptions.h"
30
31 #include "clang/CodeGen/ModuleBuilder.h"
32
33 #include "clang/Frontend/CodeGenOptions.h"
34 #include "clang/Frontend/FrontendDiagnostic.h"
35
36 #include "llvm/ADT/Twine.h"
37 #include "llvm/ADT/StringExtras.h"
38
39 #include "llvm/Bitcode/ReaderWriter.h"
40
41 #include "llvm/CodeGen/RegAllocRegistry.h"
42 #include "llvm/CodeGen/SchedulerRegistry.h"
43
44 #include "llvm/IR/Constant.h"
45 #include "llvm/IR/Constants.h"
46 #include "llvm/IR/DataLayout.h"
47 #include "llvm/IR/DebugLoc.h"
48 #include "llvm/IR/DerivedTypes.h"
49 #include "llvm/IR/Function.h"
50 #include "llvm/IR/IRBuilder.h"
51 #include "llvm/IR/IRPrintingPasses.h"
52 #include "llvm/IR/LLVMContext.h"
53 #include "llvm/IR/Metadata.h"
54 #include "llvm/IR/Module.h"
55
56 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
57
58 #include "llvm/Target/TargetMachine.h"
59 #include "llvm/Target/TargetOptions.h"
60 #include "llvm/Support/TargetRegistry.h"
61
62 #include "llvm/MC/SubtargetFeature.h"
63
64 #include "slang_assert.h"
65 #include "slang.h"
66 #include "slang_bitcode_gen.h"
67 #include "slang_rs_context.h"
68 #include "slang_rs_export_foreach.h"
69 #include "slang_rs_export_func.h"
70 #include "slang_rs_export_reduce.h"
71 #include "slang_rs_export_type.h"
72 #include "slang_rs_export_var.h"
73 #include "slang_rs_metadata.h"
74
75 #include "rs_cc_options.h"
76
77 #include "strip_unknown_attributes.h"
78
79 namespace slang {
80
CreateFunctionPasses()81 void Backend::CreateFunctionPasses() {
82 if (!mPerFunctionPasses) {
83 mPerFunctionPasses = new llvm::legacy::FunctionPassManager(mpModule);
84
85 llvm::PassManagerBuilder PMBuilder;
86 PMBuilder.OptLevel = mCodeGenOpts.OptimizationLevel;
87 PMBuilder.populateFunctionPassManager(*mPerFunctionPasses);
88 }
89 }
90
CreateModulePasses()91 void Backend::CreateModulePasses() {
92 if (!mPerModulePasses) {
93 mPerModulePasses = new llvm::legacy::PassManager();
94
95 llvm::PassManagerBuilder PMBuilder;
96 PMBuilder.OptLevel = mCodeGenOpts.OptimizationLevel;
97 PMBuilder.SizeLevel = mCodeGenOpts.OptimizeSize;
98 if (mCodeGenOpts.UnitAtATime) {
99 PMBuilder.DisableUnitAtATime = 0;
100 } else {
101 PMBuilder.DisableUnitAtATime = 1;
102 }
103
104 if (mCodeGenOpts.UnrollLoops) {
105 PMBuilder.DisableUnrollLoops = 0;
106 } else {
107 PMBuilder.DisableUnrollLoops = 1;
108 }
109
110 PMBuilder.populateModulePassManager(*mPerModulePasses);
111 // Add a pass to strip off unknown/unsupported attributes.
112 mPerModulePasses->add(createStripUnknownAttributesPass());
113 }
114 }
115
CreateCodeGenPasses()116 bool Backend::CreateCodeGenPasses() {
117 if ((mOT != Slang::OT_Assembly) && (mOT != Slang::OT_Object))
118 return true;
119
120 // Now we add passes for code emitting
121 if (mCodeGenPasses) {
122 return true;
123 } else {
124 mCodeGenPasses = new llvm::legacy::FunctionPassManager(mpModule);
125 }
126
127 // Create the TargetMachine for generating code.
128 std::string Triple = mpModule->getTargetTriple();
129
130 std::string Error;
131 const llvm::Target* TargetInfo =
132 llvm::TargetRegistry::lookupTarget(Triple, Error);
133 if (TargetInfo == nullptr) {
134 mDiagEngine.Report(clang::diag::err_fe_unable_to_create_target) << Error;
135 return false;
136 }
137
138 // Target Machine Options
139 llvm::TargetOptions Options;
140
141 // Use soft-float ABI for ARM (which is the target used by Slang during code
142 // generation). Codegen still uses hardware FPU by default. To use software
143 // floating point, add 'soft-float' feature to FeaturesStr below.
144 Options.FloatABIType = llvm::FloatABI::Soft;
145
146 // BCC needs all unknown symbols resolved at compilation time. So we don't
147 // need any relocation model.
148 llvm::Reloc::Model RM = llvm::Reloc::Static;
149
150 // This is set for the linker (specify how large of the virtual addresses we
151 // can access for all unknown symbols.)
152 llvm::CodeModel::Model CM;
153 if (mpModule->getDataLayout().getPointerSize() == 4) {
154 CM = llvm::CodeModel::Small;
155 } else {
156 // The target may have pointer size greater than 32 (e.g. x86_64
157 // architecture) may need large data address model
158 CM = llvm::CodeModel::Medium;
159 }
160
161 // Setup feature string
162 std::string FeaturesStr;
163 if (mTargetOpts.CPU.size() || mTargetOpts.Features.size()) {
164 llvm::SubtargetFeatures Features;
165
166 for (std::vector<std::string>::const_iterator
167 I = mTargetOpts.Features.begin(), E = mTargetOpts.Features.end();
168 I != E;
169 I++)
170 Features.AddFeature(*I);
171
172 FeaturesStr = Features.getString();
173 }
174
175 llvm::TargetMachine *TM =
176 TargetInfo->createTargetMachine(Triple, mTargetOpts.CPU, FeaturesStr,
177 Options, RM, CM);
178
179 // Register allocation policy:
180 // createFastRegisterAllocator: fast but bad quality
181 // createGreedyRegisterAllocator: not so fast but good quality
182 llvm::RegisterRegAlloc::setDefault((mCodeGenOpts.OptimizationLevel == 0) ?
183 llvm::createFastRegisterAllocator :
184 llvm::createGreedyRegisterAllocator);
185
186 llvm::CodeGenOpt::Level OptLevel = llvm::CodeGenOpt::Default;
187 if (mCodeGenOpts.OptimizationLevel == 0) {
188 OptLevel = llvm::CodeGenOpt::None;
189 } else if (mCodeGenOpts.OptimizationLevel == 3) {
190 OptLevel = llvm::CodeGenOpt::Aggressive;
191 }
192
193 llvm::TargetMachine::CodeGenFileType CGFT =
194 llvm::TargetMachine::CGFT_AssemblyFile;
195 if (mOT == Slang::OT_Object) {
196 CGFT = llvm::TargetMachine::CGFT_ObjectFile;
197 }
198 if (TM->addPassesToEmitFile(*mCodeGenPasses, mBufferOutStream,
199 CGFT, OptLevel)) {
200 mDiagEngine.Report(clang::diag::err_fe_unable_to_interface_with_target);
201 return false;
202 }
203
204 return true;
205 }
206
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)207 Backend::Backend(RSContext *Context, clang::DiagnosticsEngine *DiagEngine,
208 const RSCCOptions &Opts,
209 const clang::HeaderSearchOptions &HeaderSearchOpts,
210 const clang::PreprocessorOptions &PreprocessorOpts,
211 const clang::CodeGenOptions &CodeGenOpts,
212 const clang::TargetOptions &TargetOpts, PragmaList *Pragmas,
213 llvm::raw_ostream *OS, Slang::OutputType OT,
214 clang::SourceManager &SourceMgr, bool AllowRSPrefix,
215 bool IsFilterscript)
216 : ASTConsumer(), mTargetOpts(TargetOpts), mpModule(nullptr), mpOS(OS),
217 mOT(OT), mGen(nullptr), mPerFunctionPasses(nullptr),
218 mPerModulePasses(nullptr), mCodeGenPasses(nullptr),
219 mBufferOutStream(*mpOS), mContext(Context),
220 mSourceMgr(SourceMgr), mASTPrint(Opts.mASTPrint), mAllowRSPrefix(AllowRSPrefix),
221 mIsFilterscript(IsFilterscript), mExportVarMetadata(nullptr),
222 mExportFuncMetadata(nullptr), mExportForEachNameMetadata(nullptr),
223 mExportForEachSignatureMetadata(nullptr),
224 mExportReduceMetadata(nullptr),
225 mExportTypeMetadata(nullptr), mRSObjectSlotsMetadata(nullptr),
226 mRefCount(mContext->getASTContext()),
227 mASTChecker(Context, Context->getTargetAPI(), IsFilterscript),
228 mForEachHandler(Context),
229 mLLVMContext(llvm::getGlobalContext()), mDiagEngine(*DiagEngine),
230 mCodeGenOpts(CodeGenOpts), mPragmas(Pragmas) {
231 mGen = CreateLLVMCodeGen(mDiagEngine, "", HeaderSearchOpts, PreprocessorOpts,
232 mCodeGenOpts, mLLVMContext);
233 }
234
Initialize(clang::ASTContext & Ctx)235 void Backend::Initialize(clang::ASTContext &Ctx) {
236 mGen->Initialize(Ctx);
237
238 mpModule = mGen->GetModule();
239 }
240
HandleTranslationUnit(clang::ASTContext & Ctx)241 void Backend::HandleTranslationUnit(clang::ASTContext &Ctx) {
242 HandleTranslationUnitPre(Ctx);
243
244 if (mASTPrint)
245 Ctx.getTranslationUnitDecl()->dump();
246
247 mGen->HandleTranslationUnit(Ctx);
248
249 // Here, we complete a translation unit (whole translation unit is now in LLVM
250 // IR). Now, interact with LLVM backend to generate actual machine code (asm
251 // or machine code, whatever.)
252
253 // Silently ignore if we weren't initialized for some reason.
254 if (!mpModule)
255 return;
256
257 llvm::Module *M = mGen->ReleaseModule();
258 if (!M) {
259 // The module has been released by IR gen on failures, do not double free.
260 mpModule = nullptr;
261 return;
262 }
263
264 slangAssert(mpModule == M &&
265 "Unexpected module change during LLVM IR generation");
266
267 // Insert #pragma information into metadata section of module
268 if (!mPragmas->empty()) {
269 llvm::NamedMDNode *PragmaMetadata =
270 mpModule->getOrInsertNamedMetadata(Slang::PragmaMetadataName);
271 for (PragmaList::const_iterator I = mPragmas->begin(), E = mPragmas->end();
272 I != E;
273 I++) {
274 llvm::SmallVector<llvm::Metadata*, 2> Pragma;
275 // Name goes first
276 Pragma.push_back(llvm::MDString::get(mLLVMContext, I->first));
277 // And then value
278 Pragma.push_back(llvm::MDString::get(mLLVMContext, I->second));
279
280 // Create MDNode and insert into PragmaMetadata
281 PragmaMetadata->addOperand(
282 llvm::MDNode::get(mLLVMContext, Pragma));
283 }
284 }
285
286 HandleTranslationUnitPost(mpModule);
287
288 // Create passes for optimization and code emission
289
290 // Create and run per-function passes
291 CreateFunctionPasses();
292 if (mPerFunctionPasses) {
293 mPerFunctionPasses->doInitialization();
294
295 for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end();
296 I != E;
297 I++)
298 if (!I->isDeclaration())
299 mPerFunctionPasses->run(*I);
300
301 mPerFunctionPasses->doFinalization();
302 }
303
304 // Create and run module passes
305 CreateModulePasses();
306 if (mPerModulePasses)
307 mPerModulePasses->run(*mpModule);
308
309 switch (mOT) {
310 case Slang::OT_Assembly:
311 case Slang::OT_Object: {
312 if (!CreateCodeGenPasses())
313 return;
314
315 mCodeGenPasses->doInitialization();
316
317 for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end();
318 I != E;
319 I++)
320 if (!I->isDeclaration())
321 mCodeGenPasses->run(*I);
322
323 mCodeGenPasses->doFinalization();
324 break;
325 }
326 case Slang::OT_LLVMAssembly: {
327 llvm::legacy::PassManager *LLEmitPM = new llvm::legacy::PassManager();
328 LLEmitPM->add(llvm::createPrintModulePass(mBufferOutStream));
329 LLEmitPM->run(*mpModule);
330 break;
331 }
332 case Slang::OT_Bitcode: {
333 writeBitcode(mBufferOutStream, *mpModule, getTargetAPI(),
334 mCodeGenOpts.OptimizationLevel, mCodeGenOpts.getDebugInfo());
335 break;
336 }
337 case Slang::OT_Nothing: {
338 return;
339 }
340 default: {
341 slangAssert(false && "Unknown output type");
342 }
343 }
344 }
345
HandleTagDeclDefinition(clang::TagDecl * D)346 void Backend::HandleTagDeclDefinition(clang::TagDecl *D) {
347 mGen->HandleTagDeclDefinition(D);
348 }
349
CompleteTentativeDefinition(clang::VarDecl * D)350 void Backend::CompleteTentativeDefinition(clang::VarDecl *D) {
351 mGen->CompleteTentativeDefinition(D);
352 }
353
~Backend()354 Backend::~Backend() {
355 delete mpModule;
356 delete mGen;
357 delete mPerFunctionPasses;
358 delete mPerModulePasses;
359 delete mCodeGenPasses;
360 }
361
362 // 1) Add zero initialization of local RS object types
AnnotateFunction(clang::FunctionDecl * FD)363 void Backend::AnnotateFunction(clang::FunctionDecl *FD) {
364 if (FD &&
365 FD->hasBody() &&
366 !Slang::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr)) {
367 mRefCount.Init();
368 mRefCount.SetDeclContext(FD);
369 mRefCount.Visit(FD->getBody());
370 }
371 }
372
HandleTopLevelDecl(clang::DeclGroupRef D)373 bool Backend::HandleTopLevelDecl(clang::DeclGroupRef D) {
374 // Find and remember the types for rs_allocation and rs_script_call_t so
375 // they can be used later for translating rsForEach() calls.
376 for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end();
377 (mContext->getAllocationType().isNull() ||
378 mContext->getScriptCallType().isNull()) &&
379 I != E; I++) {
380 if (clang::TypeDecl* TD = llvm::dyn_cast<clang::TypeDecl>(*I)) {
381 clang::StringRef TypeName = TD->getName();
382 if (TypeName.equals("rs_allocation")) {
383 mContext->setAllocationType(TD);
384 } else if (TypeName.equals("rs_script_call_t")) {
385 mContext->setScriptCallType(TD);
386 }
387 }
388 }
389
390 // Disallow user-defined functions with prefix "rs"
391 if (!mAllowRSPrefix) {
392 // Iterate all function declarations in the program.
393 for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end();
394 I != E; I++) {
395 clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
396 if (FD == nullptr)
397 continue;
398 if (!FD->getName().startswith("rs")) // Check prefix
399 continue;
400 if (!Slang::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr))
401 mContext->ReportError(FD->getLocation(),
402 "invalid function name prefix, "
403 "\"rs\" is reserved: '%0'")
404 << FD->getName();
405 }
406 }
407
408 for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; I++) {
409 clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
410 if (FD) {
411 // Handle forward reference from pragma (see
412 // RSReducePragmaHandler::HandlePragma for backward reference).
413 mContext->markUsedByReducePragma(FD, RSContext::CheckNameYes);
414 if (FD->isGlobal()) {
415 // Check that we don't have any array parameters being misinterpreted as
416 // kernel pointers due to the C type system's array to pointer decay.
417 size_t numParams = FD->getNumParams();
418 for (size_t i = 0; i < numParams; i++) {
419 const clang::ParmVarDecl *PVD = FD->getParamDecl(i);
420 clang::QualType QT = PVD->getOriginalType();
421 if (QT->isArrayType()) {
422 mContext->ReportError(
423 PVD->getTypeSpecStartLoc(),
424 "exported function parameters may not have array type: %0")
425 << QT;
426 }
427 }
428 AnnotateFunction(FD);
429 }
430 }
431
432 if (getTargetAPI() >= SLANG_FEATURE_SINGLE_SOURCE_API) {
433 if (FD && FD->hasBody() &&
434 !Slang::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr)) {
435 if (FD->hasAttr<clang::KernelAttr>()) {
436 // Log functions with attribute "kernel" by their names, and assign
437 // them slot numbers. Any other function cannot be used in a
438 // rsForEach() or rsForEachWithOptions() call, including old-style
439 // kernel functions which are defined without the "kernel" attribute.
440 mContext->addForEach(FD);
441 }
442 // Look for any kernel launch calls and translate them into using the
443 // internal API.
444 // Report a compiler error on kernel launches inside a kernel.
445 mForEachHandler.handleForEachCalls(FD, getTargetAPI());
446 }
447 }
448 }
449
450 return mGen->HandleTopLevelDecl(D);
451 }
452
HandleTranslationUnitPre(clang::ASTContext & C)453 void Backend::HandleTranslationUnitPre(clang::ASTContext &C) {
454 clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
455
456 if (!mContext->processReducePragmas(this))
457 return;
458
459 // If we have an invalid RS/FS AST, don't check further.
460 if (!mASTChecker.Validate()) {
461 return;
462 }
463
464 if (mIsFilterscript) {
465 mContext->addPragma("rs_fp_relaxed", "");
466 }
467
468 int version = mContext->getVersion();
469 if (version == 0) {
470 // Not setting a version is an error
471 mDiagEngine.Report(
472 mSourceMgr.getLocForEndOfFile(mSourceMgr.getMainFileID()),
473 mDiagEngine.getCustomDiagID(
474 clang::DiagnosticsEngine::Error,
475 "missing pragma for version in source file"));
476 } else {
477 slangAssert(version == 1);
478 }
479
480 if (mContext->getReflectJavaPackageName().empty()) {
481 mDiagEngine.Report(
482 mSourceMgr.getLocForEndOfFile(mSourceMgr.getMainFileID()),
483 mDiagEngine.getCustomDiagID(clang::DiagnosticsEngine::Error,
484 "missing \"#pragma rs "
485 "java_package_name(com.foo.bar)\" "
486 "in source file"));
487 return;
488 }
489
490 // Create a static global destructor if necessary (to handle RS object
491 // runtime cleanup).
492 clang::FunctionDecl *FD = mRefCount.CreateStaticGlobalDtor();
493 if (FD) {
494 HandleTopLevelDecl(clang::DeclGroupRef(FD));
495 }
496
497 // Process any static function declarations
498 for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
499 E = TUDecl->decls_end(); I != E; I++) {
500 if ((I->getKind() >= clang::Decl::firstFunction) &&
501 (I->getKind() <= clang::Decl::lastFunction)) {
502 clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
503 if (FD && !FD->isGlobal()) {
504 AnnotateFunction(FD);
505 }
506 }
507 }
508 }
509
510 ///////////////////////////////////////////////////////////////////////////////
dumpExportVarInfo(llvm::Module * M)511 void Backend::dumpExportVarInfo(llvm::Module *M) {
512 int slotCount = 0;
513 if (mExportVarMetadata == nullptr)
514 mExportVarMetadata = M->getOrInsertNamedMetadata(RS_EXPORT_VAR_MN);
515
516 llvm::SmallVector<llvm::Metadata *, 2> ExportVarInfo;
517
518 // We emit slot information (#rs_object_slots) for any reference counted
519 // RS type or pointer (which can also be bound).
520
521 for (RSContext::const_export_var_iterator I = mContext->export_vars_begin(),
522 E = mContext->export_vars_end();
523 I != E;
524 I++) {
525 const RSExportVar *EV = *I;
526 const RSExportType *ET = EV->getType();
527 bool countsAsRSObject = false;
528
529 // Variable name
530 ExportVarInfo.push_back(
531 llvm::MDString::get(mLLVMContext, EV->getName().c_str()));
532
533 // Type name
534 switch (ET->getClass()) {
535 case RSExportType::ExportClassPrimitive: {
536 const RSExportPrimitiveType *PT =
537 static_cast<const RSExportPrimitiveType*>(ET);
538 ExportVarInfo.push_back(
539 llvm::MDString::get(
540 mLLVMContext, llvm::utostr_32(PT->getType())));
541 if (PT->isRSObjectType()) {
542 countsAsRSObject = true;
543 }
544 break;
545 }
546 case RSExportType::ExportClassPointer: {
547 ExportVarInfo.push_back(
548 llvm::MDString::get(
549 mLLVMContext, ("*" + static_cast<const RSExportPointerType*>(ET)
550 ->getPointeeType()->getName()).c_str()));
551 break;
552 }
553 case RSExportType::ExportClassMatrix: {
554 ExportVarInfo.push_back(
555 llvm::MDString::get(
556 mLLVMContext, llvm::utostr_32(
557 /* TODO Strange value. This pushes just a number, quite
558 * different than the other cases. What is this used for?
559 * These are the metadata values that some partner drivers
560 * want to reference (for TBAA, etc.). We may want to look
561 * at whether these provide any reasonable value (or have
562 * distinct enough values to actually depend on).
563 */
564 DataTypeRSMatrix2x2 +
565 static_cast<const RSExportMatrixType*>(ET)->getDim() - 2)));
566 break;
567 }
568 case RSExportType::ExportClassVector:
569 case RSExportType::ExportClassConstantArray:
570 case RSExportType::ExportClassRecord: {
571 ExportVarInfo.push_back(
572 llvm::MDString::get(mLLVMContext,
573 EV->getType()->getName().c_str()));
574 break;
575 }
576 }
577
578 mExportVarMetadata->addOperand(
579 llvm::MDNode::get(mLLVMContext, ExportVarInfo));
580 ExportVarInfo.clear();
581
582 if (mRSObjectSlotsMetadata == nullptr) {
583 mRSObjectSlotsMetadata =
584 M->getOrInsertNamedMetadata(RS_OBJECT_SLOTS_MN);
585 }
586
587 if (countsAsRSObject) {
588 mRSObjectSlotsMetadata->addOperand(llvm::MDNode::get(mLLVMContext,
589 llvm::MDString::get(mLLVMContext, llvm::utostr_32(slotCount))));
590 }
591
592 slotCount++;
593 }
594 }
595
dumpExportFunctionInfo(llvm::Module * M)596 void Backend::dumpExportFunctionInfo(llvm::Module *M) {
597 if (mExportFuncMetadata == nullptr)
598 mExportFuncMetadata =
599 M->getOrInsertNamedMetadata(RS_EXPORT_FUNC_MN);
600
601 llvm::SmallVector<llvm::Metadata *, 1> ExportFuncInfo;
602
603 for (RSContext::const_export_func_iterator
604 I = mContext->export_funcs_begin(),
605 E = mContext->export_funcs_end();
606 I != E;
607 I++) {
608 const RSExportFunc *EF = *I;
609
610 // Function name
611 if (!EF->hasParam()) {
612 ExportFuncInfo.push_back(llvm::MDString::get(mLLVMContext,
613 EF->getName().c_str()));
614 } else {
615 llvm::Function *F = M->getFunction(EF->getName());
616 llvm::Function *HelperFunction;
617 const std::string HelperFunctionName(".helper_" + EF->getName());
618
619 slangAssert(F && "Function marked as exported disappeared in Bitcode");
620
621 // Create helper function
622 {
623 llvm::StructType *HelperFunctionParameterTy = nullptr;
624 std::vector<bool> isStructInput;
625
626 if (!F->getArgumentList().empty()) {
627 std::vector<llvm::Type*> HelperFunctionParameterTys;
628 for (llvm::Function::arg_iterator AI = F->arg_begin(),
629 AE = F->arg_end(); AI != AE; AI++) {
630 if (AI->getType()->isPointerTy() && AI->getType()->getPointerElementType()->isStructTy()) {
631 HelperFunctionParameterTys.push_back(AI->getType()->getPointerElementType());
632 isStructInput.push_back(true);
633 } else {
634 HelperFunctionParameterTys.push_back(AI->getType());
635 isStructInput.push_back(false);
636 }
637 }
638 HelperFunctionParameterTy =
639 llvm::StructType::get(mLLVMContext, HelperFunctionParameterTys);
640 }
641
642 if (!EF->checkParameterPacketType(HelperFunctionParameterTy)) {
643 fprintf(stderr, "Failed to export function %s: parameter type "
644 "mismatch during creation of helper function.\n",
645 EF->getName().c_str());
646
647 const RSExportRecordType *Expected = EF->getParamPacketType();
648 if (Expected) {
649 fprintf(stderr, "Expected:\n");
650 Expected->getLLVMType()->dump();
651 }
652 if (HelperFunctionParameterTy) {
653 fprintf(stderr, "Got:\n");
654 HelperFunctionParameterTy->dump();
655 }
656 }
657
658 std::vector<llvm::Type*> Params;
659 if (HelperFunctionParameterTy) {
660 llvm::PointerType *HelperFunctionParameterTyP =
661 llvm::PointerType::getUnqual(HelperFunctionParameterTy);
662 Params.push_back(HelperFunctionParameterTyP);
663 }
664
665 llvm::FunctionType * HelperFunctionType =
666 llvm::FunctionType::get(F->getReturnType(),
667 Params,
668 /* IsVarArgs = */false);
669
670 HelperFunction =
671 llvm::Function::Create(HelperFunctionType,
672 llvm::GlobalValue::ExternalLinkage,
673 HelperFunctionName,
674 M);
675
676 HelperFunction->addFnAttr(llvm::Attribute::NoInline);
677 HelperFunction->setCallingConv(F->getCallingConv());
678
679 // Create helper function body
680 {
681 llvm::Argument *HelperFunctionParameter =
682 &(*HelperFunction->arg_begin());
683 llvm::BasicBlock *BB =
684 llvm::BasicBlock::Create(mLLVMContext, "entry", HelperFunction);
685 llvm::IRBuilder<> *IB = new llvm::IRBuilder<>(BB);
686 llvm::SmallVector<llvm::Value*, 6> Params;
687 llvm::Value *Idx[2];
688
689 Idx[0] =
690 llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), 0);
691
692 // getelementptr and load instruction for all elements in
693 // parameter .p
694 for (size_t i = 0; i < EF->getNumParameters(); i++) {
695 // getelementptr
696 Idx[1] = llvm::ConstantInt::get(
697 llvm::Type::getInt32Ty(mLLVMContext), i);
698
699 llvm::Value *Ptr = NULL;
700
701 Ptr = IB->CreateInBoundsGEP(HelperFunctionParameter, Idx);
702
703 // Load is only required for non-struct ptrs
704 if (isStructInput[i]) {
705 Params.push_back(Ptr);
706 } else {
707 llvm::Value *V = IB->CreateLoad(Ptr);
708 Params.push_back(V);
709 }
710 }
711
712 // Call and pass the all elements as parameter to F
713 llvm::CallInst *CI = IB->CreateCall(F, Params);
714
715 CI->setCallingConv(F->getCallingConv());
716
717 if (F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext)) {
718 IB->CreateRetVoid();
719 } else {
720 IB->CreateRet(CI);
721 }
722
723 delete IB;
724 }
725 }
726
727 ExportFuncInfo.push_back(
728 llvm::MDString::get(mLLVMContext, HelperFunctionName.c_str()));
729 }
730
731 mExportFuncMetadata->addOperand(
732 llvm::MDNode::get(mLLVMContext, ExportFuncInfo));
733 ExportFuncInfo.clear();
734 }
735 }
736
dumpExportForEachInfo(llvm::Module * M)737 void Backend::dumpExportForEachInfo(llvm::Module *M) {
738 if (mExportForEachNameMetadata == nullptr) {
739 mExportForEachNameMetadata =
740 M->getOrInsertNamedMetadata(RS_EXPORT_FOREACH_NAME_MN);
741 }
742 if (mExportForEachSignatureMetadata == nullptr) {
743 mExportForEachSignatureMetadata =
744 M->getOrInsertNamedMetadata(RS_EXPORT_FOREACH_MN);
745 }
746
747 llvm::SmallVector<llvm::Metadata *, 1> ExportForEachName;
748 llvm::SmallVector<llvm::Metadata *, 1> ExportForEachInfo;
749
750 for (RSContext::const_export_foreach_iterator
751 I = mContext->export_foreach_begin(),
752 E = mContext->export_foreach_end();
753 I != E;
754 I++) {
755 const RSExportForEach *EFE = *I;
756
757 ExportForEachName.push_back(
758 llvm::MDString::get(mLLVMContext, EFE->getName().c_str()));
759
760 mExportForEachNameMetadata->addOperand(
761 llvm::MDNode::get(mLLVMContext, ExportForEachName));
762 ExportForEachName.clear();
763
764 ExportForEachInfo.push_back(
765 llvm::MDString::get(mLLVMContext,
766 llvm::utostr_32(EFE->getSignatureMetadata())));
767
768 mExportForEachSignatureMetadata->addOperand(
769 llvm::MDNode::get(mLLVMContext, ExportForEachInfo));
770 ExportForEachInfo.clear();
771 }
772 }
773
dumpExportReduceInfo(llvm::Module * M)774 void Backend::dumpExportReduceInfo(llvm::Module *M) {
775 if (!mExportReduceMetadata) {
776 mExportReduceMetadata =
777 M->getOrInsertNamedMetadata(RS_EXPORT_REDUCE_MN);
778 }
779
780 llvm::SmallVector<llvm::Metadata *, 6> ExportReduceInfo;
781 // Add operand to ExportReduceInfo, padding out missing operands with
782 // nullptr.
783 auto addOperand = [&ExportReduceInfo](uint32_t Idx, llvm::Metadata *N) {
784 while (Idx > ExportReduceInfo.size())
785 ExportReduceInfo.push_back(nullptr);
786 ExportReduceInfo.push_back(N);
787 };
788 // Add string operand to ExportReduceInfo, padding out missing operands
789 // with nullptr.
790 // If string is empty, then do not add it unless Always is true.
791 auto addString = [&addOperand, this](uint32_t Idx, const std::string &S,
792 bool Always = true) {
793 if (Always || !S.empty())
794 addOperand(Idx, llvm::MDString::get(mLLVMContext, S));
795 };
796
797 // Add the description of the reduction kernels to the metadata node.
798 for (auto I = mContext->export_reduce_begin(),
799 E = mContext->export_reduce_end();
800 I != E; ++I) {
801 ExportReduceInfo.clear();
802
803 int Idx = 0;
804
805 addString(Idx++, (*I)->getNameReduce());
806
807 addOperand(Idx++, llvm::MDString::get(mLLVMContext, llvm::utostr_32((*I)->getAccumulatorTypeSize())));
808
809 llvm::SmallVector<llvm::Metadata *, 2> Accumulator;
810 Accumulator.push_back(
811 llvm::MDString::get(mLLVMContext, (*I)->getNameAccumulator()));
812 Accumulator.push_back(llvm::MDString::get(
813 mLLVMContext,
814 llvm::utostr_32((*I)->getAccumulatorSignatureMetadata())));
815 addOperand(Idx++, llvm::MDTuple::get(mLLVMContext, Accumulator));
816
817 addString(Idx++, (*I)->getNameInitializer(), false);
818 addString(Idx++, (*I)->getNameCombiner(), false);
819 addString(Idx++, (*I)->getNameOutConverter(), false);
820 addString(Idx++, (*I)->getNameHalter(), false);
821
822 mExportReduceMetadata->addOperand(
823 llvm::MDTuple::get(mLLVMContext, ExportReduceInfo));
824 }
825 }
826
dumpExportTypeInfo(llvm::Module * M)827 void Backend::dumpExportTypeInfo(llvm::Module *M) {
828 llvm::SmallVector<llvm::Metadata *, 1> ExportTypeInfo;
829
830 for (RSContext::const_export_type_iterator
831 I = mContext->export_types_begin(),
832 E = mContext->export_types_end();
833 I != E;
834 I++) {
835 // First, dump type name list to export
836 const RSExportType *ET = I->getValue();
837
838 ExportTypeInfo.clear();
839 // Type name
840 ExportTypeInfo.push_back(
841 llvm::MDString::get(mLLVMContext, ET->getName().c_str()));
842
843 if (ET->getClass() == RSExportType::ExportClassRecord) {
844 const RSExportRecordType *ERT =
845 static_cast<const RSExportRecordType*>(ET);
846
847 if (mExportTypeMetadata == nullptr)
848 mExportTypeMetadata =
849 M->getOrInsertNamedMetadata(RS_EXPORT_TYPE_MN);
850
851 mExportTypeMetadata->addOperand(
852 llvm::MDNode::get(mLLVMContext, ExportTypeInfo));
853
854 // Now, export struct field information to %[struct name]
855 std::string StructInfoMetadataName("%");
856 StructInfoMetadataName.append(ET->getName());
857 llvm::NamedMDNode *StructInfoMetadata =
858 M->getOrInsertNamedMetadata(StructInfoMetadataName);
859 llvm::SmallVector<llvm::Metadata *, 3> FieldInfo;
860
861 slangAssert(StructInfoMetadata->getNumOperands() == 0 &&
862 "Metadata with same name was created before");
863 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
864 FE = ERT->fields_end();
865 FI != FE;
866 FI++) {
867 const RSExportRecordType::Field *F = *FI;
868
869 // 1. field name
870 FieldInfo.push_back(llvm::MDString::get(mLLVMContext,
871 F->getName().c_str()));
872
873 // 2. field type name
874 FieldInfo.push_back(
875 llvm::MDString::get(mLLVMContext,
876 F->getType()->getName().c_str()));
877
878 StructInfoMetadata->addOperand(
879 llvm::MDNode::get(mLLVMContext, FieldInfo));
880 FieldInfo.clear();
881 }
882 } // ET->getClass() == RSExportType::ExportClassRecord
883 }
884 }
885
HandleTranslationUnitPost(llvm::Module * M)886 void Backend::HandleTranslationUnitPost(llvm::Module *M) {
887
888 if (!mContext->is64Bit()) {
889 M->setDataLayout("e-p:32:32-i64:64-v128:64:128-n32-S64");
890 }
891
892 if (!mContext->processExports())
893 return;
894
895 if (mContext->hasExportVar())
896 dumpExportVarInfo(M);
897
898 if (mContext->hasExportFunc())
899 dumpExportFunctionInfo(M);
900
901 if (mContext->hasExportForEach())
902 dumpExportForEachInfo(M);
903
904 if (mContext->hasExportReduce())
905 dumpExportReduceInfo(M);
906
907 if (mContext->hasExportType())
908 dumpExportTypeInfo(M);
909 }
910
911 } // namespace slang
912