blob: 738c8482dc96d0fdf4010b08e977d6ac65b7a1ad [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>
21
22#include "clang/AST/ASTContext.h"
23#include "clang/AST/Decl.h"
24#include "clang/AST/DeclGroup.h"
25
26#include "clang/Basic/Diagnostic.h"
27#include "clang/Basic/TargetInfo.h"
28#include "clang/Basic/TargetOptions.h"
29
30#include "clang/CodeGen/ModuleBuilder.h"
31
32#include "clang/Frontend/CodeGenOptions.h"
33#include "clang/Frontend/FrontendDiagnostic.h"
34
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -070035#include "llvm/ADT/Twine.h"
36#include "llvm/ADT/StringExtras.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080037
38#include "llvm/Bitcode/ReaderWriter.h"
39
40#include "llvm/CodeGen/RegAllocRegistry.h"
41#include "llvm/CodeGen/SchedulerRegistry.h"
42
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -070043#include "llvm/IR/Constant.h"
44#include "llvm/IR/Constants.h"
45#include "llvm/IR/DataLayout.h"
46#include "llvm/IR/DebugLoc.h"
47#include "llvm/IR/DerivedTypes.h"
48#include "llvm/IR/Function.h"
49#include "llvm/IR/IRBuilder.h"
50#include "llvm/IR/IRPrintingPasses.h"
Stephen Hines23c43582013-01-09 20:02:04 -080051#include "llvm/IR/LLVMContext.h"
Stephen Hines23c43582013-01-09 20:02:04 -080052#include "llvm/IR/Metadata.h"
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -070053#include "llvm/IR/Module.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070054
Logan Chien9207a2e2011-10-21 15:39:28 +080055#include "llvm/Transforms/IPO/PassManagerBuilder.h"
Shih-wei Liaofcc654a2011-06-22 04:47:33 -070056
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070057#include "llvm/Target/TargetMachine.h"
58#include "llvm/Target/TargetOptions.h"
Logan Chien9207a2e2011-10-21 15:39:28 +080059#include "llvm/Support/TargetRegistry.h"
Shih-wei Liao77703262011-07-02 11:30:32 -070060
61#include "llvm/MC/SubtargetFeature.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070062
Stephen Hines6e6578a2011-02-07 18:05:48 -080063#include "slang_assert.h"
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -070064#include "slang.h"
Matt Waladabd2462015-07-15 18:39:41 -070065#include "slang_bitcode_gen.h"
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -070066#include "slang_rs_context.h"
67#include "slang_rs_export_foreach.h"
68#include "slang_rs_export_func.h"
Matt Walac0c5dd82015-07-23 17:29:37 -070069#include "slang_rs_export_reduce.h"
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -070070#include "slang_rs_export_type.h"
71#include "slang_rs_export_var.h"
72#include "slang_rs_metadata.h"
73
David Gross2770d0e2015-08-03 14:58:59 -070074#include "rs_cc_options.h"
75
Stephen Hines552d8722013-12-18 12:21:50 -080076#include "strip_unknown_attributes.h"
zonr6315f762010-10-05 15:35:14 +080077
Stephen Hinese639eb52010-11-08 19:27:20 -080078namespace slang {
Shih-wei Liao462aefd2010-06-04 15:32:04 -070079
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080080void Backend::CreateFunctionPasses() {
81 if (!mPerFunctionPasses) {
Stephen Hinesc7069072015-03-18 14:53:14 -070082 mPerFunctionPasses = new llvm::legacy::FunctionPassManager(mpModule);
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080083
Shih-wei Liaofcc654a2011-06-22 04:47:33 -070084 llvm::PassManagerBuilder PMBuilder;
85 PMBuilder.OptLevel = mCodeGenOpts.OptimizationLevel;
86 PMBuilder.populateFunctionPassManager(*mPerFunctionPasses);
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080087 }
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080088}
89
90void Backend::CreateModulePasses() {
91 if (!mPerModulePasses) {
Stephen Hinesc7069072015-03-18 14:53:14 -070092 mPerModulePasses = new llvm::legacy::PassManager();
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080093
Shih-wei Liaofcc654a2011-06-22 04:47:33 -070094 llvm::PassManagerBuilder PMBuilder;
95 PMBuilder.OptLevel = mCodeGenOpts.OptimizationLevel;
96 PMBuilder.SizeLevel = mCodeGenOpts.OptimizeSize;
Shih-wei Liaofcc654a2011-06-22 04:47:33 -070097 if (mCodeGenOpts.UnitAtATime) {
98 PMBuilder.DisableUnitAtATime = 0;
99 } else {
100 PMBuilder.DisableUnitAtATime = 1;
101 }
102
103 if (mCodeGenOpts.UnrollLoops) {
104 PMBuilder.DisableUnrollLoops = 0;
105 } else {
106 PMBuilder.DisableUnrollLoops = 1;
107 }
108
Shih-wei Liaofcc654a2011-06-22 04:47:33 -0700109 PMBuilder.populateModulePassManager(*mPerModulePasses);
Stephen Hines552d8722013-12-18 12:21:50 -0800110 // Add a pass to strip off unknown/unsupported attributes.
111 mPerModulePasses->add(createStripUnknownAttributesPass());
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800112 }
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800113}
114
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700115bool Backend::CreateCodeGenPasses() {
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800116 if ((mOT != Slang::OT_Assembly) && (mOT != Slang::OT_Object))
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700117 return true;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700118
119 // Now we add passes for code emitting
120 if (mCodeGenPasses) {
121 return true;
122 } else {
Stephen Hinesc7069072015-03-18 14:53:14 -0700123 mCodeGenPasses = new llvm::legacy::FunctionPassManager(mpModule);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700124 }
125
126 // Create the TargetMachine for generating code.
127 std::string Triple = mpModule->getTargetTriple();
128
129 std::string Error;
130 const llvm::Target* TargetInfo =
131 llvm::TargetRegistry::lookupTarget(Triple, Error);
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700132 if (TargetInfo == nullptr) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800133 mDiagEngine.Report(clang::diag::err_fe_unable_to_create_target) << Error;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700134 return false;
135 }
136
Logan Chienac4e1852011-12-16 13:37:10 +0800137 // Target Machine Options
138 llvm::TargetOptions Options;
139
Pirama Arumuga Nainar167bd792015-06-30 19:46:13 -0700140 // Use soft-float ABI for ARM (which is the target used by Slang during code
141 // generation). Codegen still uses hardware FPU by default. To use software
142 // floating point, add 'soft-float' feature to FeaturesStr below.
143 Options.FloatABIType = llvm::FloatABI::Soft;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700144
145 // BCC needs all unknown symbols resolved at compilation time. So we don't
146 // need any relocation model.
Logan Chienab992e52011-07-20 22:06:52 +0800147 llvm::Reloc::Model RM = llvm::Reloc::Static;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700148
Zonr Chang41ebf532010-10-13 18:29:18 +0800149 // This is set for the linker (specify how large of the virtual addresses we
150 // can access for all unknown symbols.)
Logan Chien9207a2e2011-10-21 15:39:28 +0800151 llvm::CodeModel::Model CM;
Stephen Hines0b754582015-04-07 13:59:57 -0700152 if (mpModule->getDataLayout().getPointerSize() == 4) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800153 CM = llvm::CodeModel::Small;
154 } else {
Zonr Chang41ebf532010-10-13 18:29:18 +0800155 // The target may have pointer size greater than 32 (e.g. x86_64
156 // architecture) may need large data address model
Logan Chien9207a2e2011-10-21 15:39:28 +0800157 CM = llvm::CodeModel::Medium;
158 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700159
160 // Setup feature string
161 std::string FeaturesStr;
162 if (mTargetOpts.CPU.size() || mTargetOpts.Features.size()) {
163 llvm::SubtargetFeatures Features;
164
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700165 for (std::vector<std::string>::const_iterator
166 I = mTargetOpts.Features.begin(), E = mTargetOpts.Features.end();
167 I != E;
168 I++)
169 Features.AddFeature(*I);
170
171 FeaturesStr = Features.getString();
172 }
Logan Chien9207a2e2011-10-21 15:39:28 +0800173
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700174 llvm::TargetMachine *TM =
Logan Chien9207a2e2011-10-21 15:39:28 +0800175 TargetInfo->createTargetMachine(Triple, mTargetOpts.CPU, FeaturesStr,
Logan Chienac4e1852011-12-16 13:37:10 +0800176 Options, RM, CM);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700177
178 // Register scheduler
179 llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
180
181 // Register allocation policy:
182 // createFastRegisterAllocator: fast but bad quality
Logan Chien2c6bad52011-11-15 15:57:33 +0800183 // createGreedyRegisterAllocator: not so fast but good quality
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700184 llvm::RegisterRegAlloc::setDefault((mCodeGenOpts.OptimizationLevel == 0) ?
185 llvm::createFastRegisterAllocator :
Logan Chien2c6bad52011-11-15 15:57:33 +0800186 llvm::createGreedyRegisterAllocator);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700187
188 llvm::CodeGenOpt::Level OptLevel = llvm::CodeGenOpt::Default;
Shih-wei Liao77703262011-07-02 11:30:32 -0700189 if (mCodeGenOpts.OptimizationLevel == 0) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700190 OptLevel = llvm::CodeGenOpt::None;
Shih-wei Liao77703262011-07-02 11:30:32 -0700191 } else if (mCodeGenOpts.OptimizationLevel == 3) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700192 OptLevel = llvm::CodeGenOpt::Aggressive;
Shih-wei Liao77703262011-07-02 11:30:32 -0700193 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700194
195 llvm::TargetMachine::CodeGenFileType CGFT =
zonr6315f762010-10-05 15:35:14 +0800196 llvm::TargetMachine::CGFT_AssemblyFile;
Shih-wei Liao77703262011-07-02 11:30:32 -0700197 if (mOT == Slang::OT_Object) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700198 CGFT = llvm::TargetMachine::CGFT_ObjectFile;
Shih-wei Liao77703262011-07-02 11:30:32 -0700199 }
Pirama Arumuga Nainar21cc0182015-05-06 11:17:16 -0700200 if (TM->addPassesToEmitFile(*mCodeGenPasses, mBufferOutStream,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700201 CGFT, OptLevel)) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800202 mDiagEngine.Report(clang::diag::err_fe_unable_to_interface_with_target);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700203 return false;
204 }
205
206 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700207}
208
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700209Backend::Backend(RSContext *Context, clang::DiagnosticsEngine *DiagEngine,
David Gross2770d0e2015-08-03 14:58:59 -0700210 const RSCCOptions &Opts, const clang::CodeGenOptions &CodeGenOpts,
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700211 const clang::TargetOptions &TargetOpts, PragmaList *Pragmas,
212 llvm::raw_ostream *OS, Slang::OutputType OT,
213 clang::SourceManager &SourceMgr, bool AllowRSPrefix,
214 bool IsFilterscript)
215 : ASTConsumer(), mTargetOpts(TargetOpts), mpModule(nullptr), mpOS(OS),
216 mOT(OT), mGen(nullptr), mPerFunctionPasses(nullptr),
Pirama Arumuga Nainar21cc0182015-05-06 11:17:16 -0700217 mPerModulePasses(nullptr), mCodeGenPasses(nullptr),
218 mBufferOutStream(*mpOS), mContext(Context),
David Gross2770d0e2015-08-03 14:58:59 -0700219 mSourceMgr(SourceMgr), mASTPrint(Opts.mASTPrint), mAllowRSPrefix(AllowRSPrefix),
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700220 mIsFilterscript(IsFilterscript), mExportVarMetadata(nullptr),
221 mExportFuncMetadata(nullptr), mExportForEachNameMetadata(nullptr),
Matt Walac0c5dd82015-07-23 17:29:37 -0700222 mExportForEachSignatureMetadata(nullptr), mExportReduceMetadata(nullptr),
223 mExportTypeMetadata(nullptr), mRSObjectSlotsMetadata(nullptr),
224 mRefCount(mContext->getASTContext()),
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700225 mASTChecker(Context, Context->getTargetAPI(), IsFilterscript),
Yang Nifb40ee22015-10-13 20:34:06 +0000226 mForEachHandler(Context),
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700227 mLLVMContext(llvm::getGlobalContext()), mDiagEngine(*DiagEngine),
228 mCodeGenOpts(CodeGenOpts), mPragmas(Pragmas) {
Stephen Hinesc7069072015-03-18 14:53:14 -0700229 mGen = CreateLLVMCodeGen(mDiagEngine, "", mCodeGenOpts, mLLVMContext);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700230}
231
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700232void Backend::Initialize(clang::ASTContext &Ctx) {
233 mGen->Initialize(Ctx);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700234
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700235 mpModule = mGen->GetModule();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700236}
237
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700238void Backend::HandleTranslationUnit(clang::ASTContext &Ctx) {
Zonr Chang68fc02c2010-10-13 19:09:19 +0800239 HandleTranslationUnitPre(Ctx);
240
David Gross2770d0e2015-08-03 14:58:59 -0700241 if (mASTPrint)
242 Ctx.getTranslationUnitDecl()->dump();
243
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700244 mGen->HandleTranslationUnit(Ctx);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700245
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700246 // Here, we complete a translation unit (whole translation unit is now in LLVM
247 // IR). Now, interact with LLVM backend to generate actual machine code (asm
248 // or machine code, whatever.)
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700249
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700250 // Silently ignore if we weren't initialized for some reason.
Zonr Chang41ebf532010-10-13 18:29:18 +0800251 if (!mpModule)
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700252 return;
253
254 llvm::Module *M = mGen->ReleaseModule();
255 if (!M) {
256 // The module has been released by IR gen on failures, do not double free.
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700257 mpModule = nullptr;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700258 return;
259 }
260
Stephen Hines6e6578a2011-02-07 18:05:48 -0800261 slangAssert(mpModule == M &&
262 "Unexpected module change during LLVM IR generation");
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700263
264 // Insert #pragma information into metadata section of module
Stephen Hines3fd0a942011-01-18 12:27:39 -0800265 if (!mPragmas->empty()) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700266 llvm::NamedMDNode *PragmaMetadata =
267 mpModule->getOrInsertNamedMetadata(Slang::PragmaMetadataName);
Stephen Hines3fd0a942011-01-18 12:27:39 -0800268 for (PragmaList::const_iterator I = mPragmas->begin(), E = mPragmas->end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700269 I != E;
270 I++) {
Stephen Hinesc7069072015-03-18 14:53:14 -0700271 llvm::SmallVector<llvm::Metadata*, 2> Pragma;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700272 // Name goes first
273 Pragma.push_back(llvm::MDString::get(mLLVMContext, I->first));
274 // And then value
275 Pragma.push_back(llvm::MDString::get(mLLVMContext, I->second));
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700276
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700277 // Create MDNode and insert into PragmaMetadata
278 PragmaMetadata->addOperand(
Stephen Hines18c88292011-07-14 22:46:15 -0700279 llvm::MDNode::get(mLLVMContext, Pragma));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700280 }
281 }
282
Zonr Chang68fc02c2010-10-13 19:09:19 +0800283 HandleTranslationUnitPost(mpModule);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700284
285 // Create passes for optimization and code emission
286
287 // Create and run per-function passes
288 CreateFunctionPasses();
289 if (mPerFunctionPasses) {
290 mPerFunctionPasses->doInitialization();
291
292 for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end();
293 I != E;
294 I++)
295 if (!I->isDeclaration())
296 mPerFunctionPasses->run(*I);
297
298 mPerFunctionPasses->doFinalization();
299 }
300
301 // Create and run module passes
302 CreateModulePasses();
303 if (mPerModulePasses)
304 mPerModulePasses->run(*mpModule);
305
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800306 switch (mOT) {
307 case Slang::OT_Assembly:
308 case Slang::OT_Object: {
zonr6315f762010-10-05 15:35:14 +0800309 if (!CreateCodeGenPasses())
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700310 return;
311
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700312 mCodeGenPasses->doInitialization();
313
314 for (llvm::Module::iterator I = mpModule->begin(), E = mpModule->end();
315 I != E;
316 I++)
zonr6315f762010-10-05 15:35:14 +0800317 if (!I->isDeclaration())
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700318 mCodeGenPasses->run(*I);
319
320 mCodeGenPasses->doFinalization();
321 break;
322 }
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800323 case Slang::OT_LLVMAssembly: {
Stephen Hinesc7069072015-03-18 14:53:14 -0700324 llvm::legacy::PassManager *LLEmitPM = new llvm::legacy::PassManager();
Pirama Arumuga Nainar21cc0182015-05-06 11:17:16 -0700325 LLEmitPM->add(llvm::createPrintModulePass(mBufferOutStream));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700326 LLEmitPM->run(*mpModule);
327 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700328 }
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800329 case Slang::OT_Bitcode: {
Matt Waladabd2462015-07-15 18:39:41 -0700330 writeBitcode(mBufferOutStream, *mpModule, getTargetAPI(),
Stephen McGroartyb130e152015-07-23 16:55:02 +0100331 mCodeGenOpts.OptimizationLevel, mCodeGenOpts.getDebugInfo());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700332 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700333 }
Zonr Chang3a9ca1f2010-10-06 17:52:56 +0800334 case Slang::OT_Nothing: {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700335 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700336 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700337 default: {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800338 slangAssert(false && "Unknown output type");
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700339 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700340 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700341
Pirama Arumuga Nainar21cc0182015-05-06 11:17:16 -0700342 mBufferOutStream.flush();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700343}
344
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700345void Backend::HandleTagDeclDefinition(clang::TagDecl *D) {
346 mGen->HandleTagDeclDefinition(D);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700347}
348
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700349void Backend::CompleteTentativeDefinition(clang::VarDecl *D) {
350 mGen->CompleteTentativeDefinition(D);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700351}
352
353Backend::~Backend() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700354 delete mpModule;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700355 delete mGen;
356 delete mPerFunctionPasses;
357 delete mPerModulePasses;
358 delete mCodeGenPasses;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700359}
Stephen Hinese639eb52010-11-08 19:27:20 -0800360
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700361// 1) Add zero initialization of local RS object types
362void Backend::AnnotateFunction(clang::FunctionDecl *FD) {
363 if (FD &&
364 FD->hasBody() &&
365 !Slang::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr)) {
366 mRefCount.Init();
367 mRefCount.Visit(FD->getBody());
368 }
369}
370
Yang Nifb40ee22015-10-13 20:34:06 +0000371void Backend::LowerRSForEachCall(clang::FunctionDecl *FD) {
372 // Skip this AST walking for lower API levels.
373 if (getTargetAPI() < SLANG_DEVELOPMENT_TARGET_API) {
374 return;
375 }
376
377 if (!FD || !FD->hasBody() ||
378 Slang::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr)) {
379 return;
380 }
381
382 mForEachHandler.VisitStmt(FD->getBody());
383}
384
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700385bool Backend::HandleTopLevelDecl(clang::DeclGroupRef D) {
Yang Nifb40ee22015-10-13 20:34:06 +0000386 // Find and remember the TypeDecl for rs_allocation so we can use it
387 // later during the compilation
388 for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end();
389 I != E; I++) {
390 clang::TypeDecl* TD = llvm::dyn_cast<clang::TypeDecl>(*I);
391 if (TD && TD->getName().equals("rs_allocation")) {
392 mContext->addAllocationType(TD);
393 break;
394 }
395 }
396
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700397 // Disallow user-defined functions with prefix "rs"
398 if (!mAllowRSPrefix) {
399 // Iterate all function declarations in the program.
400 for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end();
401 I != E; I++) {
402 clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
403 if (FD == nullptr)
404 continue;
405 if (!FD->getName().startswith("rs")) // Check prefix
406 continue;
407 if (!Slang::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr))
408 mContext->ReportError(FD->getLocation(),
409 "invalid function name prefix, "
410 "\"rs\" is reserved: '%0'")
411 << FD->getName();
412 }
413 }
414
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700415 for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; I++) {
416 clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
Yang Nifb40ee22015-10-13 20:34:06 +0000417 // Process any non-static function declarations
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700418 if (FD && FD->isGlobal()) {
419 // Check that we don't have any array parameters being misintrepeted as
420 // kernel pointers due to the C type system's array to pointer decay.
421 size_t numParams = FD->getNumParams();
422 for (size_t i = 0; i < numParams; i++) {
423 const clang::ParmVarDecl *PVD = FD->getParamDecl(i);
424 clang::QualType QT = PVD->getOriginalType();
425 if (QT->isArrayType()) {
426 mContext->ReportError(
427 PVD->getTypeSpecStartLoc(),
428 "exported function parameters may not have array type: %0")
429 << QT;
430 }
431 }
432 AnnotateFunction(FD);
433 }
Yang Nifb40ee22015-10-13 20:34:06 +0000434
435 if (RSExportForEach::isRSForEachFunc(getTargetAPI(), FD)) {
436 // Log kernels by their names, and assign them slot numbers.
437 if (getTargetAPI() == SLANG_DEVELOPMENT_TARGET_API &&
438 !Slang::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr)) {
439 mContext->addForEach(FD);
440 }
441 } else {
442 // Look for any kernel launch calls and translate them into using the
443 // internal API.
444 // TODO: Simply ignores kernel launch inside a kernel for now.
445 // Needs more rigorous and comprehensive checks.
446 LowerRSForEachCall(FD);
447 }
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700448 }
Yang Nifb40ee22015-10-13 20:34:06 +0000449
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700450 return mGen->HandleTopLevelDecl(D);
451}
452
453void Backend::HandleTranslationUnitPre(clang::ASTContext &C) {
454 clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
455
456 // If we have an invalid RS/FS AST, don't check further.
457 if (!mASTChecker.Validate()) {
458 return;
459 }
460
461 if (mIsFilterscript) {
462 mContext->addPragma("rs_fp_relaxed", "");
463 }
464
465 int version = mContext->getVersion();
466 if (version == 0) {
467 // Not setting a version is an error
468 mDiagEngine.Report(
469 mSourceMgr.getLocForEndOfFile(mSourceMgr.getMainFileID()),
470 mDiagEngine.getCustomDiagID(
471 clang::DiagnosticsEngine::Error,
472 "missing pragma for version in source file"));
473 } else {
474 slangAssert(version == 1);
475 }
476
477 if (mContext->getReflectJavaPackageName().empty()) {
478 mDiagEngine.Report(
479 mSourceMgr.getLocForEndOfFile(mSourceMgr.getMainFileID()),
480 mDiagEngine.getCustomDiagID(clang::DiagnosticsEngine::Error,
481 "missing \"#pragma rs "
482 "java_package_name(com.foo.bar)\" "
483 "in source file"));
484 return;
485 }
486
487 // Create a static global destructor if necessary (to handle RS object
488 // runtime cleanup).
489 clang::FunctionDecl *FD = mRefCount.CreateStaticGlobalDtor();
490 if (FD) {
491 HandleTopLevelDecl(clang::DeclGroupRef(FD));
492 }
493
494 // Process any static function declarations
495 for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
496 E = TUDecl->decls_end(); I != E; I++) {
497 if ((I->getKind() >= clang::Decl::firstFunction) &&
498 (I->getKind() <= clang::Decl::lastFunction)) {
499 clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
500 if (FD && !FD->isGlobal()) {
501 AnnotateFunction(FD);
502 }
503 }
504 }
505}
506
507///////////////////////////////////////////////////////////////////////////////
508void Backend::dumpExportVarInfo(llvm::Module *M) {
509 int slotCount = 0;
510 if (mExportVarMetadata == nullptr)
511 mExportVarMetadata = M->getOrInsertNamedMetadata(RS_EXPORT_VAR_MN);
512
513 llvm::SmallVector<llvm::Metadata *, 2> ExportVarInfo;
514
515 // We emit slot information (#rs_object_slots) for any reference counted
516 // RS type or pointer (which can also be bound).
517
518 for (RSContext::const_export_var_iterator I = mContext->export_vars_begin(),
519 E = mContext->export_vars_end();
520 I != E;
521 I++) {
522 const RSExportVar *EV = *I;
523 const RSExportType *ET = EV->getType();
524 bool countsAsRSObject = false;
525
526 // Variable name
527 ExportVarInfo.push_back(
528 llvm::MDString::get(mLLVMContext, EV->getName().c_str()));
529
530 // Type name
531 switch (ET->getClass()) {
532 case RSExportType::ExportClassPrimitive: {
533 const RSExportPrimitiveType *PT =
534 static_cast<const RSExportPrimitiveType*>(ET);
535 ExportVarInfo.push_back(
536 llvm::MDString::get(
537 mLLVMContext, llvm::utostr_32(PT->getType())));
538 if (PT->isRSObjectType()) {
539 countsAsRSObject = true;
540 }
541 break;
542 }
543 case RSExportType::ExportClassPointer: {
544 ExportVarInfo.push_back(
545 llvm::MDString::get(
546 mLLVMContext, ("*" + static_cast<const RSExportPointerType*>(ET)
547 ->getPointeeType()->getName()).c_str()));
548 break;
549 }
550 case RSExportType::ExportClassMatrix: {
551 ExportVarInfo.push_back(
552 llvm::MDString::get(
553 mLLVMContext, llvm::utostr_32(
554 /* TODO Strange value. This pushes just a number, quite
555 * different than the other cases. What is this used for?
556 * These are the metadata values that some partner drivers
557 * want to reference (for TBAA, etc.). We may want to look
558 * at whether these provide any reasonable value (or have
559 * distinct enough values to actually depend on).
560 */
561 DataTypeRSMatrix2x2 +
562 static_cast<const RSExportMatrixType*>(ET)->getDim() - 2)));
563 break;
564 }
565 case RSExportType::ExportClassVector:
566 case RSExportType::ExportClassConstantArray:
567 case RSExportType::ExportClassRecord: {
568 ExportVarInfo.push_back(
569 llvm::MDString::get(mLLVMContext,
570 EV->getType()->getName().c_str()));
571 break;
572 }
573 }
574
575 mExportVarMetadata->addOperand(
576 llvm::MDNode::get(mLLVMContext, ExportVarInfo));
577 ExportVarInfo.clear();
578
579 if (mRSObjectSlotsMetadata == nullptr) {
580 mRSObjectSlotsMetadata =
581 M->getOrInsertNamedMetadata(RS_OBJECT_SLOTS_MN);
582 }
583
584 if (countsAsRSObject) {
585 mRSObjectSlotsMetadata->addOperand(llvm::MDNode::get(mLLVMContext,
586 llvm::MDString::get(mLLVMContext, llvm::utostr_32(slotCount))));
587 }
588
589 slotCount++;
590 }
591}
592
593void Backend::dumpExportFunctionInfo(llvm::Module *M) {
594 if (mExportFuncMetadata == nullptr)
595 mExportFuncMetadata =
596 M->getOrInsertNamedMetadata(RS_EXPORT_FUNC_MN);
597
598 llvm::SmallVector<llvm::Metadata *, 1> ExportFuncInfo;
599
600 for (RSContext::const_export_func_iterator
601 I = mContext->export_funcs_begin(),
602 E = mContext->export_funcs_end();
603 I != E;
604 I++) {
605 const RSExportFunc *EF = *I;
606
607 // Function name
608 if (!EF->hasParam()) {
609 ExportFuncInfo.push_back(llvm::MDString::get(mLLVMContext,
610 EF->getName().c_str()));
611 } else {
612 llvm::Function *F = M->getFunction(EF->getName());
613 llvm::Function *HelperFunction;
614 const std::string HelperFunctionName(".helper_" + EF->getName());
615
616 slangAssert(F && "Function marked as exported disappeared in Bitcode");
617
618 // Create helper function
619 {
620 llvm::StructType *HelperFunctionParameterTy = nullptr;
621 std::vector<bool> isStructInput;
622
623 if (!F->getArgumentList().empty()) {
624 std::vector<llvm::Type*> HelperFunctionParameterTys;
625 for (llvm::Function::arg_iterator AI = F->arg_begin(),
626 AE = F->arg_end(); AI != AE; AI++) {
627 if (AI->getType()->isPointerTy() && AI->getType()->getPointerElementType()->isStructTy()) {
628 HelperFunctionParameterTys.push_back(AI->getType()->getPointerElementType());
629 isStructInput.push_back(true);
630 } else {
631 HelperFunctionParameterTys.push_back(AI->getType());
632 isStructInput.push_back(false);
633 }
634 }
635 HelperFunctionParameterTy =
636 llvm::StructType::get(mLLVMContext, HelperFunctionParameterTys);
637 }
638
639 if (!EF->checkParameterPacketType(HelperFunctionParameterTy)) {
640 fprintf(stderr, "Failed to export function %s: parameter type "
641 "mismatch during creation of helper function.\n",
642 EF->getName().c_str());
643
644 const RSExportRecordType *Expected = EF->getParamPacketType();
645 if (Expected) {
646 fprintf(stderr, "Expected:\n");
647 Expected->getLLVMType()->dump();
648 }
649 if (HelperFunctionParameterTy) {
650 fprintf(stderr, "Got:\n");
651 HelperFunctionParameterTy->dump();
652 }
653 }
654
655 std::vector<llvm::Type*> Params;
656 if (HelperFunctionParameterTy) {
657 llvm::PointerType *HelperFunctionParameterTyP =
658 llvm::PointerType::getUnqual(HelperFunctionParameterTy);
659 Params.push_back(HelperFunctionParameterTyP);
660 }
661
662 llvm::FunctionType * HelperFunctionType =
663 llvm::FunctionType::get(F->getReturnType(),
664 Params,
665 /* IsVarArgs = */false);
666
667 HelperFunction =
668 llvm::Function::Create(HelperFunctionType,
669 llvm::GlobalValue::ExternalLinkage,
670 HelperFunctionName,
671 M);
672
673 HelperFunction->addFnAttr(llvm::Attribute::NoInline);
674 HelperFunction->setCallingConv(F->getCallingConv());
675
676 // Create helper function body
677 {
678 llvm::Argument *HelperFunctionParameter =
679 &(*HelperFunction->arg_begin());
680 llvm::BasicBlock *BB =
681 llvm::BasicBlock::Create(mLLVMContext, "entry", HelperFunction);
682 llvm::IRBuilder<> *IB = new llvm::IRBuilder<>(BB);
683 llvm::SmallVector<llvm::Value*, 6> Params;
684 llvm::Value *Idx[2];
685
686 Idx[0] =
687 llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), 0);
688
689 // getelementptr and load instruction for all elements in
690 // parameter .p
691 for (size_t i = 0; i < EF->getNumParameters(); i++) {
692 // getelementptr
693 Idx[1] = llvm::ConstantInt::get(
694 llvm::Type::getInt32Ty(mLLVMContext), i);
695
696 llvm::Value *Ptr = NULL;
697
698 Ptr = IB->CreateInBoundsGEP(HelperFunctionParameter, Idx);
699
700 // Load is only required for non-struct ptrs
701 if (isStructInput[i]) {
702 Params.push_back(Ptr);
703 } else {
704 llvm::Value *V = IB->CreateLoad(Ptr);
705 Params.push_back(V);
706 }
707 }
708
709 // Call and pass the all elements as parameter to F
710 llvm::CallInst *CI = IB->CreateCall(F, Params);
711
712 CI->setCallingConv(F->getCallingConv());
713
Yang Nifb40ee22015-10-13 20:34:06 +0000714 if (F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext)) {
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700715 IB->CreateRetVoid();
Yang Nifb40ee22015-10-13 20:34:06 +0000716 } else {
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700717 IB->CreateRet(CI);
Yang Nifb40ee22015-10-13 20:34:06 +0000718 }
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700719
720 delete IB;
721 }
722 }
723
724 ExportFuncInfo.push_back(
725 llvm::MDString::get(mLLVMContext, HelperFunctionName.c_str()));
726 }
727
728 mExportFuncMetadata->addOperand(
729 llvm::MDNode::get(mLLVMContext, ExportFuncInfo));
730 ExportFuncInfo.clear();
731 }
732}
733
734void Backend::dumpExportForEachInfo(llvm::Module *M) {
735 if (mExportForEachNameMetadata == nullptr) {
736 mExportForEachNameMetadata =
737 M->getOrInsertNamedMetadata(RS_EXPORT_FOREACH_NAME_MN);
738 }
739 if (mExportForEachSignatureMetadata == nullptr) {
740 mExportForEachSignatureMetadata =
741 M->getOrInsertNamedMetadata(RS_EXPORT_FOREACH_MN);
742 }
743
744 llvm::SmallVector<llvm::Metadata *, 1> ExportForEachName;
745 llvm::SmallVector<llvm::Metadata *, 1> ExportForEachInfo;
746
747 for (RSContext::const_export_foreach_iterator
748 I = mContext->export_foreach_begin(),
749 E = mContext->export_foreach_end();
750 I != E;
751 I++) {
752 const RSExportForEach *EFE = *I;
753
754 ExportForEachName.push_back(
755 llvm::MDString::get(mLLVMContext, EFE->getName().c_str()));
756
757 mExportForEachNameMetadata->addOperand(
758 llvm::MDNode::get(mLLVMContext, ExportForEachName));
759 ExportForEachName.clear();
760
761 ExportForEachInfo.push_back(
762 llvm::MDString::get(mLLVMContext,
763 llvm::utostr_32(EFE->getSignatureMetadata())));
764
765 mExportForEachSignatureMetadata->addOperand(
766 llvm::MDNode::get(mLLVMContext, ExportForEachInfo));
767 ExportForEachInfo.clear();
768 }
769}
770
Matt Walac0c5dd82015-07-23 17:29:37 -0700771void Backend::dumpExportReduceInfo(llvm::Module *M) {
772 if (!mExportReduceMetadata) {
773 mExportReduceMetadata = M->getOrInsertNamedMetadata(RS_EXPORT_REDUCE_MN);
774 }
775
776 llvm::SmallVector<llvm::Metadata *, 1> ExportReduceInfo;
777
778 // Add the names of the reduce-style kernel functions to the metadata node.
779 for (auto I = mContext->export_reduce_begin(),
780 E = mContext->export_reduce_end(); I != E; ++I) {
781 ExportReduceInfo.clear();
782
783 ExportReduceInfo.push_back(
784 llvm::MDString::get(mLLVMContext, (*I)->getName().c_str()));
785
786 mExportReduceMetadata->addOperand(
787 llvm::MDNode::get(mLLVMContext, ExportReduceInfo));
788 }
789}
790
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700791void Backend::dumpExportTypeInfo(llvm::Module *M) {
792 llvm::SmallVector<llvm::Metadata *, 1> ExportTypeInfo;
793
794 for (RSContext::const_export_type_iterator
795 I = mContext->export_types_begin(),
796 E = mContext->export_types_end();
797 I != E;
798 I++) {
799 // First, dump type name list to export
800 const RSExportType *ET = I->getValue();
801
802 ExportTypeInfo.clear();
803 // Type name
804 ExportTypeInfo.push_back(
805 llvm::MDString::get(mLLVMContext, ET->getName().c_str()));
806
807 if (ET->getClass() == RSExportType::ExportClassRecord) {
808 const RSExportRecordType *ERT =
809 static_cast<const RSExportRecordType*>(ET);
810
811 if (mExportTypeMetadata == nullptr)
812 mExportTypeMetadata =
813 M->getOrInsertNamedMetadata(RS_EXPORT_TYPE_MN);
814
815 mExportTypeMetadata->addOperand(
816 llvm::MDNode::get(mLLVMContext, ExportTypeInfo));
817
818 // Now, export struct field information to %[struct name]
819 std::string StructInfoMetadataName("%");
820 StructInfoMetadataName.append(ET->getName());
821 llvm::NamedMDNode *StructInfoMetadata =
822 M->getOrInsertNamedMetadata(StructInfoMetadataName);
823 llvm::SmallVector<llvm::Metadata *, 3> FieldInfo;
824
825 slangAssert(StructInfoMetadata->getNumOperands() == 0 &&
826 "Metadata with same name was created before");
827 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
828 FE = ERT->fields_end();
829 FI != FE;
830 FI++) {
831 const RSExportRecordType::Field *F = *FI;
832
833 // 1. field name
834 FieldInfo.push_back(llvm::MDString::get(mLLVMContext,
835 F->getName().c_str()));
836
837 // 2. field type name
838 FieldInfo.push_back(
839 llvm::MDString::get(mLLVMContext,
840 F->getType()->getName().c_str()));
841
842 StructInfoMetadata->addOperand(
843 llvm::MDNode::get(mLLVMContext, FieldInfo));
844 FieldInfo.clear();
845 }
846 } // ET->getClass() == RSExportType::ExportClassRecord
847 }
848}
849
850void Backend::HandleTranslationUnitPost(llvm::Module *M) {
851
852 if (!mContext->is64Bit()) {
853 M->setDataLayout("e-p:32:32-i64:64-v128:64:128-n32-S64");
854 }
855
Yang Nifb40ee22015-10-13 20:34:06 +0000856 if (!mContext->processExports()) {
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700857 return;
858 }
859
860 if (mContext->hasExportVar())
861 dumpExportVarInfo(M);
862
863 if (mContext->hasExportFunc())
864 dumpExportFunctionInfo(M);
865
866 if (mContext->hasExportForEach())
867 dumpExportForEachInfo(M);
868
Matt Walac0c5dd82015-07-23 17:29:37 -0700869 if (mContext->hasExportReduce())
870 dumpExportReduceInfo(M);
871
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -0700872 if (mContext->hasExportType())
873 dumpExportTypeInfo(M);
874}
875
Stephen Hinese639eb52010-11-08 19:27:20 -0800876} // namespace slang