blob: 1671ceed0910fbffde703f8e45009d6feff9210a [file] [log] [blame]
Yang Ni6749f542016-11-07 20:20:49 -08001/*
2 * Copyright 2016, 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 "RSSPIRVWriter.h"
18
19#include "SPIRVModule.h"
20#include "bcinfo/MetadataExtractor.h"
21
22#include "llvm/ADT/StringMap.h"
23#include "llvm/ADT/Triple.h"
24#include "llvm/IR/LegacyPassManager.h"
25#include "llvm/IR/Module.h"
26#include "llvm/Support/CommandLine.h"
27#include "llvm/Support/Debug.h"
28#include "llvm/Support/SPIRV.h"
29#include "llvm/Support/raw_ostream.h"
30#include "llvm/Transforms/IPO.h"
31
32#include "GlobalMergePass.h"
Yang Niec9360e2016-11-21 15:50:27 -080033#include "InlinePreparationPass.h"
Yang Ni6749f542016-11-07 20:20:49 -080034#include "ReflectionPass.h"
I-Jui (Ray) Sung3523b2f2017-01-19 17:18:23 -080035#include "RemoveNonkernelsPass.h"
Yang Ni6749f542016-11-07 20:20:49 -080036
37#include <fstream>
38#include <sstream>
39
40#define DEBUG_TYPE "rs2spirv-writer"
41
42using namespace llvm;
43using namespace SPIRV;
44
45namespace llvm {
46FunctionPass *createPromoteMemoryToRegisterPass();
Rahul Chaudhry7974fc02017-02-09 12:33:28 -080047} // namespace llvm
Yang Ni6749f542016-11-07 20:20:49 -080048
49namespace rs2spirv {
50
51static cl::opt<std::string> WrapperOutputFile("wo",
52 cl::desc("Wrapper output file"),
53 cl::value_desc("filename.spt"));
54
Yang Ni6749f542016-11-07 20:20:49 -080055static void HandleTargetTriple(Module &M) {
56 Triple TT(M.getTargetTriple());
57 auto Arch = TT.getArch();
58
59 StringRef NewTriple;
60 switch (Arch) {
61 default:
62 llvm_unreachable("Unrecognized architecture");
63 break;
64 case Triple::arm:
65 NewTriple = "spir-unknown-unknown";
66 break;
67 case Triple::aarch64:
68 NewTriple = "spir64-unknown-unknown";
69 break;
70 case Triple::spir:
71 case Triple::spir64:
72 DEBUG(dbgs() << "!!! Already a spir triple !!!\n");
73 }
74
75 DEBUG(dbgs() << "New triple:\t" << NewTriple << "\n");
76 M.setTargetTriple(NewTriple);
77}
78
I-Jui (Ray) Sung3523b2f2017-01-19 17:18:23 -080079void addPassesForRS2SPIRV(llvm::legacy::PassManager &PassMgr,
80 bcinfo::MetadataExtractor &Extractor) {
81 PassMgr.add(createInlinePreparationPass(Extractor));
82 PassMgr.add(createAlwaysInlinerPass());
83 PassMgr.add(createRemoveNonkernelsPass(Extractor));
84 // Delete unreachable globals.
85 PassMgr.add(createGlobalDCEPass());
86 // Remove dead debug info.
87 PassMgr.add(createStripDeadDebugInfoPass());
88 // Remove dead func decls.
89 PassMgr.add(createStripDeadPrototypesPass());
Yang Ni6749f542016-11-07 20:20:49 -080090 PassMgr.add(createGlobalMergePass());
91 PassMgr.add(createPromoteMemoryToRegisterPass());
92 PassMgr.add(createTransOCLMD());
93 // TODO: investigate removal of OCLTypeToSPIRV pass.
94 PassMgr.add(createOCLTypeToSPIRV());
95 PassMgr.add(createSPIRVRegularizeLLVM());
96 PassMgr.add(createSPIRVLowerConstExpr());
97 PassMgr.add(createSPIRVLowerBool());
Yang Ni6749f542016-11-07 20:20:49 -080098}
99
100bool WriteSPIRV(Module *M, llvm::raw_ostream &OS, std::string &ErrMsg) {
101 std::unique_ptr<SPIRVModule> BM(SPIRVModule::createSPIRVModule());
102
103 HandleTargetTriple(*M);
104
105 bcinfo::MetadataExtractor ME(M);
106 if (!ME.extract()) {
107 errs() << "Could not extract metadata\n";
108 return false;
109 }
110 DEBUG(dbgs() << "Metadata extracted\n");
111
112 llvm::legacy::PassManager PassMgr;
I-Jui (Ray) Sung3523b2f2017-01-19 17:18:23 -0800113 addPassesForRS2SPIRV(PassMgr, ME);
Yang Ni6749f542016-11-07 20:20:49 -0800114
115 std::ofstream WrapperF;
116 if (!WrapperOutputFile.empty()) {
117 WrapperF.open(WrapperOutputFile, std::ios::trunc);
118 if (!WrapperF.good()) {
119 errs() << "Could not create/open file:\t" << WrapperOutputFile << "\n";
120 return false;
121 }
122 DEBUG(dbgs() << "Wrapper output:\t" << WrapperOutputFile << "\n");
123 PassMgr.add(createReflectionPass(WrapperF, ME));
124 }
125
126 PassMgr.add(createLLVMToSPIRV(BM.get()));
127 PassMgr.run(*M);
128 DEBUG(M->dump());
129
130 if (BM->getError(ErrMsg) != SPIRVEC_Success)
131 return false;
132
133 OS << *BM;
134
135 return true;
136}
137
Yang Ni6749f542016-11-07 20:20:49 -0800138} // namespace rs2spirv