blob: 02069987a211aab167997c12cf3da9ded6d80daf [file] [log] [blame]
Zonr Changc383a502010-10-12 01:52:08 +08001/*
Stephen Hines5e3b6772012-03-21 08:02:10 -07002 * Copyright 2010-2012, The Android Open Source Project
Zonr Changc383a502010-10-12 01:52:08 +08003 *
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
zonr6315f762010-10-05 15:35:14 +080017#include "slang_backend.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070018
Stephen Hinese639eb52010-11-08 19:27:20 -080019#include <string>
20#include <vector>
David Gross37dbf5c2017-03-29 20:54:15 +000021#include <iostream>
Stephen Hinese639eb52010-11-08 19:27:20 -080022
23#include "clang/AST/ASTContext.h"
David Gross65f23ed2016-01-08 12:04:59 -080024#include "clang/AST/Attr.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080025#include "clang/AST/Decl.h"
26#include "clang/AST/DeclGroup.h"
David Gross37dbf5c2017-03-29 20:54:15 +000027#include "clang/AST/RecordLayout.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080028
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
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -070038#include "llvm/ADT/Twine.h"
39#include "llvm/ADT/StringExtras.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080040
41#include "llvm/Bitcode/ReaderWriter.h"
42
43#include "llvm/CodeGen/RegAllocRegistry.h"
44#include "llvm/CodeGen/SchedulerRegistry.h"
45
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -070046#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"
Stephen Hines23c43582013-01-09 20:02:04 -080054#include "llvm/IR/LLVMContext.h"
Stephen Hines23c43582013-01-09 20:02:04 -080055#include "llvm/IR/Metadata.h"
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -070056#include "llvm/IR/Module.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070057
Logan Chien9207a2e2011-10-21 15:39:28 +080058#include "llvm/Transforms/IPO/PassManagerBuilder.h"
Shih-wei Liaofcc654a2011-06-22 04:47:33 -070059
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070060#include "llvm/Target/TargetMachine.h"
61#include "llvm/Target/TargetOptions.h"
Logan Chien9207a2e2011-10-21 15:39:28 +080062#include "llvm/Support/TargetRegistry.h"
Shih-wei Liao77703262011-07-02 11:30:32 -070063
64#include "llvm/MC/SubtargetFeature.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070065
Stephen Hines6e6578a2011-02-07 18:05:48 -080066#include "slang_assert.h"
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -070067#include "slang.h"
Matt Waladabd2462015-07-15 18:39:41 -070068#include "slang_bitcode_gen.h"
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -070069#include "slang_rs_context.h"
70#include "slang_rs_export_foreach.h"
71#include "slang_rs_export_func.h"
Matt Walac0c5dd82015-07-23 17:29:37 -070072#include "slang_rs_export_reduce.h"
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -070073#include "slang_rs_export_type.h"
74#include "slang_rs_export_var.h"
75#include "slang_rs_metadata.h"
76
David Gross2770d0e2015-08-03 14:58:59 -070077#include "rs_cc_options.h"
78
David Gross97ac1a52017-05-16 15:27:52 -070079#include "StripUnkAttr/strip_unknown_attributes_pass.h"
zonr6315f762010-10-05 15:35:14 +080080
Luke Drummond8bcf2382016-12-13 20:15:55 +000081namespace {
82class VersionInfoPass : public llvm::ModulePass {
83 const clang::CodeGenOptions &mCodeGenOpts;
84
85 const char *getSlangLLVMVersion() const {
86 if (mCodeGenOpts.getDebugInfo() != clang::codegenoptions::NoDebugInfo)
87 return LLVM_VERSION_STRING;
88 return nullptr;
89 }
90
91public:
92 static char ID;
93 VersionInfoPass(const clang::CodeGenOptions &codegenOpts)
94 : ModulePass(ID), mCodeGenOpts(codegenOpts) {}
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
108char VersionInfoPass::ID = 0;
109
110llvm::ModulePass *createVersionInfoPass(const clang::CodeGenOptions &cgo) {
111 return new VersionInfoPass(cgo);
112}
113}
114
Stephen Hinese639eb52010-11-08 19:27:20 -0800115namespace slang {
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700116
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800117void Backend::CreateFunctionPasses() {
118 if (!mPerFunctionPasses) {
Stephen Hinesc7069072015-03-18 14:53:14 -0700119 mPerFunctionPasses = new llvm::legacy::FunctionPassManager(mpModule);
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800120
Shih-wei Liaofcc654a2011-06-22 04:47:33 -0700121 llvm::PassManagerBuilder PMBuilder;
122 PMBuilder.OptLevel = mCodeGenOpts.OptimizationLevel;
123 PMBuilder.populateFunctionPassManager(*mPerFunctionPasses);
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800124 }
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800125}
126
127void Backend::CreateModulePasses() {
128 if (!mPerModulePasses) {
Stephen Hinesc7069072015-03-18 14:53:14 -0700129 mPerModulePasses = new llvm::legacy::PassManager();
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800130
Shih-wei Liaofcc654a2011-06-22 04:47:33 -0700131 llvm::PassManagerBuilder PMBuilder;
132 PMBuilder.OptLevel = mCodeGenOpts.OptimizationLevel;
133 PMBuilder.SizeLevel = mCodeGenOpts.OptimizeSize;
Pirama Arumuga Nainarb6a14352016-07-26 11:39:47 -0700134 PMBuilder.DisableUnitAtATime = 0; // TODO Pirama confirm if this is right
Shih-wei Liaofcc654a2011-06-22 04:47:33 -0700135
136 if (mCodeGenOpts.UnrollLoops) {
137 PMBuilder.DisableUnrollLoops = 0;
138 } else {
139 PMBuilder.DisableUnrollLoops = 1;
140 }
141
Shih-wei Liaofcc654a2011-06-22 04:47:33 -0700142 PMBuilder.populateModulePassManager(*mPerModulePasses);
Stephen Hines552d8722013-12-18 12:21:50 -0800143 // Add a pass to strip off unknown/unsupported attributes.
144 mPerModulePasses->add(createStripUnknownAttributesPass());
Luke Drummond8bcf2382016-12-13 20:15:55 +0000145 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 }
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800150 }
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800151}
152
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700153bool Backend::CreateCodeGenPasses() {
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800154 if ((mOT != Slang::OT_Assembly) && (mOT != Slang::OT_Object))
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700155 return true;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700156
157 // Now we add passes for code emitting
158 if (mCodeGenPasses) {
159 return true;
160 } else {
Stephen Hinesc7069072015-03-18 14:53:14 -0700161 mCodeGenPasses = new llvm::legacy::FunctionPassManager(mpModule);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700162 }
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);
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700170 if (TargetInfo == nullptr) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800171 mDiagEngine.Report(clang::diag::err_fe_unable_to_create_target) << Error;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700172 return false;
173 }
174
Logan Chienac4e1852011-12-16 13:37:10 +0800175 // Target Machine Options
176 llvm::TargetOptions Options;
177
Pirama Arumuga Nainar167bd792015-06-30 19:46:13 -0700178 // 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;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700182
183 // BCC needs all unknown symbols resolved at compilation time. So we don't
184 // need any relocation model.
Logan Chienab992e52011-07-20 22:06:52 +0800185 llvm::Reloc::Model RM = llvm::Reloc::Static;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700186
Zonr Chang41ebf532010-10-13 18:29:18 +0800187 // This is set for the linker (specify how large of the virtual addresses we
188 // can access for all unknown symbols.)
Logan Chien9207a2e2011-10-21 15:39:28 +0800189 llvm::CodeModel::Model CM;
Stephen Hines0b754582015-04-07 13:59:57 -0700190 if (mpModule->getDataLayout().getPointerSize() == 4) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800191 CM = llvm::CodeModel::Small;
192 } else {
Zonr Chang41ebf532010-10-13 18:29:18 +0800193 // The target may have pointer size greater than 32 (e.g. x86_64
194 // architecture) may need large data address model
Logan Chien9207a2e2011-10-21 15:39:28 +0800195 CM = llvm::CodeModel::Medium;
196 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700197
198 // Setup feature string
199 std::string FeaturesStr;
200 if (mTargetOpts.CPU.size() || mTargetOpts.Features.size()) {
201 llvm::SubtargetFeatures Features;
202
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700203 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 }
Logan Chien9207a2e2011-10-21 15:39:28 +0800211
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700212 llvm::TargetMachine *TM =
Logan Chien9207a2e2011-10-21 15:39:28 +0800213 TargetInfo->createTargetMachine(Triple, mTargetOpts.CPU, FeaturesStr,
Logan Chienac4e1852011-12-16 13:37:10 +0800214 Options, RM, CM);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700215
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700216 // Register allocation policy:
217 // createFastRegisterAllocator: fast but bad quality
Logan Chien2c6bad52011-11-15 15:57:33 +0800218 // createGreedyRegisterAllocator: not so fast but good quality
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700219 llvm::RegisterRegAlloc::setDefault((mCodeGenOpts.OptimizationLevel == 0) ?
220 llvm::createFastRegisterAllocator :
Logan Chien2c6bad52011-11-15 15:57:33 +0800221 llvm::createGreedyRegisterAllocator);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700222
223 llvm::CodeGenOpt::Level OptLevel = llvm::CodeGenOpt::Default;
Shih-wei Liao77703262011-07-02 11:30:32 -0700224 if (mCodeGenOpts.OptimizationLevel == 0) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700225 OptLevel = llvm::CodeGenOpt::None;
Shih-wei Liao77703262011-07-02 11:30:32 -0700226 } else if (mCodeGenOpts.OptimizationLevel == 3) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700227 OptLevel = llvm::CodeGenOpt::Aggressive;
Shih-wei Liao77703262011-07-02 11:30:32 -0700228 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700229
230 llvm::TargetMachine::CodeGenFileType CGFT =
zonr6315f762010-10-05 15:35:14 +0800231 llvm::TargetMachine::CGFT_AssemblyFile;
Shih-wei Liao77703262011-07-02 11:30:32 -0700232 if (mOT == Slang::OT_Object) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700233 CGFT = llvm::TargetMachine::CGFT_ObjectFile;
Shih-wei Liao77703262011-07-02 11:30:32 -0700234 }
Pirama Arumuga Nainar21cc0182015-05-06 11:17:16 -0700235 if (TM->addPassesToEmitFile(*mCodeGenPasses, mBufferOutStream,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700236 CGFT, OptLevel)) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800237 mDiagEngine.Report(clang::diag::err_fe_unable_to_interface_with_target);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700238 return false;
239 }
240
241 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700242}
243
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700244Backend::Backend(RSContext *Context, clang::DiagnosticsEngine *DiagEngine,
Pirama Arumuga Nainar8f093e02016-03-03 23:56:27 -0800245 const RSCCOptions &Opts,
246 const clang::HeaderSearchOptions &HeaderSearchOpts,
247 const clang::PreprocessorOptions &PreprocessorOpts,
248 const clang::CodeGenOptions &CodeGenOpts,
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700249 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),
Pirama Arumuga Nainar21cc0182015-05-06 11:17:16 -0700255 mPerModulePasses(nullptr), mCodeGenPasses(nullptr),
256 mBufferOutStream(*mpOS), mContext(Context),
David Gross2770d0e2015-08-03 14:58:59 -0700257 mSourceMgr(SourceMgr), mASTPrint(Opts.mASTPrint), mAllowRSPrefix(AllowRSPrefix),
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700258 mIsFilterscript(IsFilterscript), mExportVarMetadata(nullptr),
259 mExportFuncMetadata(nullptr), mExportForEachNameMetadata(nullptr),
David Grossdbf5b612016-02-03 10:41:56 -0800260 mExportForEachSignatureMetadata(nullptr),
David Gross8ee018b2016-06-02 14:46:55 -0700261 mExportReduceMetadata(nullptr),
Matt Walac0c5dd82015-07-23 17:29:37 -0700262 mExportTypeMetadata(nullptr), mRSObjectSlotsMetadata(nullptr),
263 mRefCount(mContext->getASTContext()),
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700264 mASTChecker(Context, Context->getTargetAPI(), IsFilterscript),
Yang Nifb40ee22015-10-13 20:34:06 +0000265 mForEachHandler(Context),
Pirama Arumuga Nainarb6a14352016-07-26 11:39:47 -0700266 mLLVMContext(slang::getGlobalLLVMContext()), mDiagEngine(*DiagEngine),
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700267 mCodeGenOpts(CodeGenOpts), mPragmas(Pragmas) {
Pirama Arumuga Nainar8f093e02016-03-03 23:56:27 -0800268 mGen = CreateLLVMCodeGen(mDiagEngine, "", HeaderSearchOpts, PreprocessorOpts,
269 mCodeGenOpts, mLLVMContext);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700270}
271
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700272void Backend::Initialize(clang::ASTContext &Ctx) {
273 mGen->Initialize(Ctx);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700274
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700275 mpModule = mGen->GetModule();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700276}
277
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700278void Backend::HandleTranslationUnit(clang::ASTContext &Ctx) {
Zonr Chang68fc02c2010-10-13 19:09:19 +0800279 HandleTranslationUnitPre(Ctx);
280
David Gross2770d0e2015-08-03 14:58:59 -0700281 if (mASTPrint)
282 Ctx.getTranslationUnitDecl()->dump();
283
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700284 mGen->HandleTranslationUnit(Ctx);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700285
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700286 // 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.)
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700289
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700290 // Silently ignore if we weren't initialized for some reason.
Zonr Chang41ebf532010-10-13 18:29:18 +0800291 if (!mpModule)
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700292 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.
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700297 mpModule = nullptr;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700298 return;
299 }
300
Stephen Hines6e6578a2011-02-07 18:05:48 -0800301 slangAssert(mpModule == M &&
302 "Unexpected module change during LLVM IR generation");
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700303
304 // Insert #pragma information into metadata section of module
Stephen Hines3fd0a942011-01-18 12:27:39 -0800305 if (!mPragmas->empty()) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700306 llvm::NamedMDNode *PragmaMetadata =
307 mpModule->getOrInsertNamedMetadata(Slang::PragmaMetadataName);
Stephen Hines3fd0a942011-01-18 12:27:39 -0800308 for (PragmaList::const_iterator I = mPragmas->begin(), E = mPragmas->end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700309 I != E;
310 I++) {
Stephen Hinesc7069072015-03-18 14:53:14 -0700311 llvm::SmallVector<llvm::Metadata*, 2> Pragma;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700312 // 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));
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700316
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700317 // Create MDNode and insert into PragmaMetadata
318 PragmaMetadata->addOperand(
Stephen Hines18c88292011-07-14 22:46:15 -0700319 llvm::MDNode::get(mLLVMContext, Pragma));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700320 }
321 }
322
Zonr Chang68fc02c2010-10-13 19:09:19 +0800323 HandleTranslationUnitPost(mpModule);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700324
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
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800346 switch (mOT) {
347 case Slang::OT_Assembly:
348 case Slang::OT_Object: {
zonr6315f762010-10-05 15:35:14 +0800349 if (!CreateCodeGenPasses())
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700350 return;
351
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700352 mCodeGenPasses->doInitialization();
353
354 for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end();
355 I != E;
356 I++)
zonr6315f762010-10-05 15:35:14 +0800357 if (!I->isDeclaration())
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700358 mCodeGenPasses->run(*I);
359
360 mCodeGenPasses->doFinalization();
361 break;
362 }
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800363 case Slang::OT_LLVMAssembly: {
Stephen Hinesc7069072015-03-18 14:53:14 -0700364 llvm::legacy::PassManager *LLEmitPM = new llvm::legacy::PassManager();
Pirama Arumuga Nainar21cc0182015-05-06 11:17:16 -0700365 LLEmitPM->add(llvm::createPrintModulePass(mBufferOutStream));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700366 LLEmitPM->run(*mpModule);
367 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700368 }
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800369 case Slang::OT_Bitcode: {
Matt Waladabd2462015-07-15 18:39:41 -0700370 writeBitcode(mBufferOutStream, *mpModule, getTargetAPI(),
Stephen McGroartyb130e152015-07-23 16:55:02 +0100371 mCodeGenOpts.OptimizationLevel, mCodeGenOpts.getDebugInfo());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700372 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700373 }
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800374 case Slang::OT_Nothing: {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700375 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700376 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700377 default: {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800378 slangAssert(false && "Unknown output type");
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700379 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700380 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700381}
382
David Gross37dbf5c2017-03-29 20:54:15 +0000383// Insert explicit padding fields into struct to follow the current layout.
384//
385// A similar algorithm is present in PadHelperFunctionStruct().
386void 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());
I-Jui (Ray) Sungec686802017-04-06 15:14:50 -0700451 if (RD->hasAttrs())
452 RDForLayout->setAttrs(RD->getAttrs());
David Gross37dbf5c2017-03-29 20:54:15 +0000453 RDForLayout->completeDefinition();
454
455 // move all fields from RD to RDForLayout
456 for (const auto &info : FieldsInfo) {
457 RD->removeDecl(info.second);
I-Jui (Ray) Sungec686802017-04-06 15:14:50 -0700458 info.second->setLexicalDeclContext(RDForLayout);
David Gross37dbf5c2017-03-29 20:54:15 +0000459 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);
I-Jui (Ray) Sungec686802017-04-06 15:14:50 -0700551 info.second->setLexicalDeclContext(RD);
David Gross37dbf5c2017-03-29 20:54:15 +0000552 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
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700564void Backend::HandleTagDeclDefinition(clang::TagDecl *D) {
David Gross37dbf5c2017-03-29 20:54:15 +0000565 // 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 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700585 mGen->HandleTagDeclDefinition(D);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700586}
587
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700588void Backend::CompleteTentativeDefinition(clang::VarDecl *D) {
589 mGen->CompleteTentativeDefinition(D);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700590}
591
592Backend::~Backend() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700593 delete mpModule;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700594 delete mGen;
595 delete mPerFunctionPasses;
596 delete mPerModulePasses;
597 delete mCodeGenPasses;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700598}
Stephen Hinese639eb52010-11-08 19:27:20 -0800599
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700600// 1) Add zero initialization of local RS object types
601void Backend::AnnotateFunction(clang::FunctionDecl *FD) {
602 if (FD &&
603 FD->hasBody() &&
I-Jui (Ray) Sungc8f5b2d2016-12-01 13:40:06 -0800604 !FD->isImplicit() &&
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700605 !Slang::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr)) {
606 mRefCount.Init();
Yang Ni283a6cf2016-01-15 16:37:04 -0800607 mRefCount.SetDeclContext(FD);
Yang Ni31d2ea32017-04-14 15:44:23 -0700608 mRefCount.HandleParamsAndLocals(FD);
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700609 }
610}
611
612bool Backend::HandleTopLevelDecl(clang::DeclGroupRef D) {
Yang Ni2615f382015-12-02 18:46:47 -0800613 // 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")) {
Yang Ni88f21e12015-11-18 15:59:00 -0800622 mContext->setAllocationType(TD);
Yang Ni2615f382015-12-02 18:46:47 -0800623 } else if (TypeName.equals("rs_script_call_t")) {
624 mContext->setScriptCallType(TD);
Yang Ni88f21e12015-11-18 15:59:00 -0800625 }
626 }
627 }
628
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700629 // 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
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700647 for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; I++) {
648 clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
David Gross65f23ed2016-01-08 12:04:59 -0800649 if (FD) {
David Gross5e306b92016-02-08 16:45:12 -0800650 // Handle forward reference from pragma (see
651 // RSReducePragmaHandler::HandlePragma for backward reference).
652 mContext->markUsedByReducePragma(FD, RSContext::CheckNameYes);
David Gross65f23ed2016-01-08 12:04:59 -0800653 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 }
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700669 }
Yang Nifb40ee22015-10-13 20:34:06 +0000670
Yang Ni40bac5d2016-05-09 09:29:11 -0700671 if (getTargetAPI() >= SLANG_FEATURE_SINGLE_SOURCE_API) {
I-Jui (Ray) Sungc8f5b2d2016-12-01 13:40:06 -0800672 if (FD && FD->hasBody() && !FD->isImplicit() &&
Yang Ni9319dfc2016-02-25 15:14:37 -0800673 !Slang::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr)) {
Pirama Arumuga Nainarb6a14352016-07-26 11:39:47 -0700674 if (FD->hasAttr<clang::RenderScriptKernelAttr>()) {
Yang Ni40bac5d2016-05-09 09:29:11 -0700675 // 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.
Yang Ni9319dfc2016-02-25 15:14:37 -0800679 mContext->addForEach(FD);
Yang Ni19467492015-10-27 15:24:41 -0700680 }
Yang Ni19467492015-10-27 15:24:41 -0700681 // Look for any kernel launch calls and translate them into using the
682 // internal API.
Yang Ni40bac5d2016-05-09 09:29:11 -0700683 // Report a compiler error on kernel launches inside a kernel.
Yang Ni9319dfc2016-02-25 15:14:37 -0800684 mForEachHandler.handleForEachCalls(FD, getTargetAPI());
Yang Nifb40ee22015-10-13 20:34:06 +0000685 }
Yang Nifb40ee22015-10-13 20:34:06 +0000686 }
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700687 }
Yang Nifb40ee22015-10-13 20:34:06 +0000688
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700689 return mGen->HandleTopLevelDecl(D);
690}
691
692void Backend::HandleTranslationUnitPre(clang::ASTContext &C) {
693 clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
694
David Gross5e306b92016-02-08 16:45:12 -0800695 if (!mContext->processReducePragmas(this))
David Gross65f23ed2016-01-08 12:04:59 -0800696 return;
697
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700698 // 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///////////////////////////////////////////////////////////////////////////////
750void 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(
Pirama Arumuga Nainarb6a14352016-07-26 11:39:47 -0700779 mLLVMContext, llvm::utostr(PT->getType())));
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700780 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(
Pirama Arumuga Nainarb6a14352016-07-26 11:39:47 -0700795 mLLVMContext, llvm::utostr(
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700796 /* 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,
Pirama Arumuga Nainarb6a14352016-07-26 11:39:47 -0700828 llvm::MDString::get(mLLVMContext, llvm::utostr(slotCount))));
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700829 }
830
831 slotCount++;
832 }
833}
834
David Gross37dbf5c2017-03-29 20:54:15 +0000835// A similar algorithm is present in Backend::PadStruct().
836static 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
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700890void 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 {
David Gross37dbf5c2017-03-29 20:54:15 +0000917 llvm::StructType *OrigHelperFunctionParameterTy = nullptr;
918 llvm::StructType *PaddedHelperFunctionParameterTy = nullptr;
919
920 std::vector<unsigned> OrigFieldNumToPaddedFieldNum;
I-Jui (Ray) Sung48b49b42017-06-30 11:06:09 -0700921 std::vector<bool> isPassedViaPtr;
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700922
923 if (!F->getArgumentList().empty()) {
924 std::vector<llvm::Type*> HelperFunctionParameterTys;
925 for (llvm::Function::arg_iterator AI = F->arg_begin(),
I-Jui (Ray) Sung48b49b42017-06-30 11:06:09 -0700926 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;
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700942 }
I-Jui (Ray) Sung48b49b42017-06-30 11:06:09 -0700943 HelperFunctionParameterTys.push_back(Ty);
944 isPassedViaPtr.push_back(viaPtr);
945 }
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700946 }
David Gross37dbf5c2017-03-29 20:54:15 +0000947 OrigHelperFunctionParameterTy =
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700948 llvm::StructType::get(mLLVMContext, HelperFunctionParameterTys);
David Gross37dbf5c2017-03-29 20:54:15 +0000949 PadHelperFunctionStruct(M,
950 &PaddedHelperFunctionParameterTy, &OrigFieldNumToPaddedFieldNum,
951 OrigHelperFunctionParameterTy);
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700952 }
953
David Gross37dbf5c2017-03-29 20:54:15 +0000954 if (!EF->checkParameterPacketType(OrigHelperFunctionParameterTy)) {
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700955 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 }
David Gross37dbf5c2017-03-29 20:54:15 +0000964 if (OrigHelperFunctionParameterTy) {
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700965 fprintf(stderr, "Got:\n");
David Gross37dbf5c2017-03-29 20:54:15 +0000966 OrigHelperFunctionParameterTy->dump();
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700967 }
I-Jui (Ray) Sung48b49b42017-06-30 11:06:09 -0700968 abort();
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700969 }
970
971 std::vector<llvm::Type*> Params;
David Gross37dbf5c2017-03-29 20:54:15 +0000972 if (PaddedHelperFunctionParameterTy) {
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700973 llvm::PointerType *HelperFunctionParameterTyP =
David Gross37dbf5c2017-03-29 20:54:15 +0000974 llvm::PointerType::getUnqual(PaddedHelperFunctionParameterTy);
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700975 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
David Gross37dbf5c2017-03-29 20:54:15 +00001007 for (size_t origFieldNum = 0; origFieldNum < EF->getNumParameters(); origFieldNum++) {
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -07001008 // getelementptr
1009 Idx[1] = llvm::ConstantInt::get(
David Gross37dbf5c2017-03-29 20:54:15 +00001010 llvm::Type::getInt32Ty(mLLVMContext), OrigFieldNumToPaddedFieldNum[origFieldNum]);
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -07001011
1012 llvm::Value *Ptr = NULL;
1013
1014 Ptr = IB->CreateInBoundsGEP(HelperFunctionParameter, Idx);
1015
1016 // Load is only required for non-struct ptrs
I-Jui (Ray) Sung48b49b42017-06-30 11:06:09 -07001017 if (isPassedViaPtr[origFieldNum]) {
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -07001018 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
Yang Nifb40ee22015-10-13 20:34:06 +00001030 if (F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext)) {
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -07001031 IB->CreateRetVoid();
Yang Nifb40ee22015-10-13 20:34:06 +00001032 } else {
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -07001033 IB->CreateRet(CI);
Yang Nifb40ee22015-10-13 20:34:06 +00001034 }
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -07001035
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
1050void 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,
Pirama Arumuga Nainarb6a14352016-07-26 11:39:47 -07001079 llvm::utostr(EFE->getSignatureMetadata())));
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -07001080
1081 mExportForEachSignatureMetadata->addOperand(
1082 llvm::MDNode::get(mLLVMContext, ExportForEachInfo));
1083 ExportForEachInfo.clear();
1084 }
1085}
1086
David Gross8ee018b2016-06-02 14:46:55 -07001087void Backend::dumpExportReduceInfo(llvm::Module *M) {
1088 if (!mExportReduceMetadata) {
1089 mExportReduceMetadata =
1090 M->getOrInsertNamedMetadata(RS_EXPORT_REDUCE_MN);
David Gross15e44e62015-11-10 11:12:48 -08001091 }
1092
David Gross8ee018b2016-06-02 14:46:55 -07001093 llvm::SmallVector<llvm::Metadata *, 6> ExportReduceInfo;
1094 // Add operand to ExportReduceInfo, padding out missing operands with
David Gross15e44e62015-11-10 11:12:48 -08001095 // nullptr.
David Gross8ee018b2016-06-02 14:46:55 -07001096 auto addOperand = [&ExportReduceInfo](uint32_t Idx, llvm::Metadata *N) {
1097 while (Idx > ExportReduceInfo.size())
1098 ExportReduceInfo.push_back(nullptr);
1099 ExportReduceInfo.push_back(N);
David Gross15e44e62015-11-10 11:12:48 -08001100 };
David Gross8ee018b2016-06-02 14:46:55 -07001101 // Add string operand to ExportReduceInfo, padding out missing operands
David Gross15e44e62015-11-10 11:12:48 -08001102 // 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.
David Gross8ee018b2016-06-02 14:46:55 -07001111 for (auto I = mContext->export_reduce_begin(),
1112 E = mContext->export_reduce_end();
David Gross15e44e62015-11-10 11:12:48 -08001113 I != E; ++I) {
David Gross8ee018b2016-06-02 14:46:55 -07001114 ExportReduceInfo.clear();
David Gross15e44e62015-11-10 11:12:48 -08001115
David Gross65f23ed2016-01-08 12:04:59 -08001116 int Idx = 0;
1117
1118 addString(Idx++, (*I)->getNameReduce());
1119
Pirama Arumuga Nainarb6a14352016-07-26 11:39:47 -07001120 addOperand(Idx++, llvm::MDString::get(mLLVMContext, llvm::utostr((*I)->getAccumulatorTypeSize())));
David Gross15e44e62015-11-10 11:12:48 -08001121
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,
Pirama Arumuga Nainarb6a14352016-07-26 11:39:47 -07001127 llvm::utostr((*I)->getAccumulatorSignatureMetadata())));
David Gross65f23ed2016-01-08 12:04:59 -08001128 addOperand(Idx++, llvm::MDTuple::get(mLLVMContext, Accumulator));
David Gross15e44e62015-11-10 11:12:48 -08001129
David Gross65f23ed2016-01-08 12:04:59 -08001130 addString(Idx++, (*I)->getNameInitializer(), false);
1131 addString(Idx++, (*I)->getNameCombiner(), false);
1132 addString(Idx++, (*I)->getNameOutConverter(), false);
1133 addString(Idx++, (*I)->getNameHalter(), false);
David Gross15e44e62015-11-10 11:12:48 -08001134
David Gross8ee018b2016-06-02 14:46:55 -07001135 mExportReduceMetadata->addOperand(
1136 llvm::MDTuple::get(mLLVMContext, ExportReduceInfo));
David Gross15e44e62015-11-10 11:12:48 -08001137 }
1138}
1139
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -07001140void 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
1199void 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
David Gross65f23ed2016-01-08 12:04:59 -08001205 if (!mContext->processExports())
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -07001206 return;
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -07001207
1208 if (mContext->hasExportVar())
1209 dumpExportVarInfo(M);
1210
1211 if (mContext->hasExportFunc())
1212 dumpExportFunctionInfo(M);
1213
1214 if (mContext->hasExportForEach())
1215 dumpExportForEachInfo(M);
1216
David Gross8ee018b2016-06-02 14:46:55 -07001217 if (mContext->hasExportReduce())
1218 dumpExportReduceInfo(M);
David Gross15e44e62015-11-10 11:12:48 -08001219
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -07001220 if (mContext->hasExportType())
1221 dumpExportTypeInfo(M);
1222}
1223
Stephen Hinese639eb52010-11-08 19:27:20 -08001224} // namespace slang