1bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni/*
2bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni * Copyright 2017, The Android Open Source Project
3bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni *
4bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni * Licensed under the Apache License, Version 2.0 (the "License");
5bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni * you may not use this file except in compliance with the License.
6bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni * You may obtain a copy of the License at
7bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni *
8bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni *     http://www.apache.org/licenses/LICENSE-2.0
9bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni *
10bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni * Unless required by applicable law or agreed to in writing, software
11bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni * distributed under the License is distributed on an "AS IS" BASIS,
12bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni * See the License for the specific language governing permissions and
14bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni * limitations under the License.
15bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni */
16bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
17bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni#include "Wrapper.h"
18bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
193f30b6202dd5ad6ff66959131d216405850ed152Yang Ni#include "llvm/IR/Module.h"
203f30b6202dd5ad6ff66959131d216405850ed152Yang Ni
21bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni#include "Builtin.h"
22eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni#include "Context.h"
239d73d08c545462e706ef6951952acff94c37605aI-Jui (Ray) Sung#include "GlobalAllocSPIRITPass.h"
24bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni#include "RSAllocationUtils.h"
25bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni#include "bcinfo/MetadataExtractor.h"
26bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni#include "builder.h"
27bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni#include "instructions.h"
28bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni#include "module.h"
293f30b6202dd5ad6ff66959131d216405850ed152Yang Ni#include "pass.h"
303f30b6202dd5ad6ff66959131d216405850ed152Yang Ni
31eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni#include <sstream>
323f30b6202dd5ad6ff66959131d216405850ed152Yang Ni#include <vector>
33bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
34bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Niusing bcinfo::MetadataExtractor;
353f30b6202dd5ad6ff66959131d216405850ed152Yang Ni
36bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ninamespace android {
37bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ninamespace spirit {
38bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
39bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang NiVariableInst *AddBuffer(Instruction *elementType, uint32_t binding, Builder &b,
40bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni                        Module *m) {
41bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  auto ArrTy = m->getRuntimeArrayType(elementType);
42bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  const size_t stride = m->getSize(elementType);
43bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  ArrTy->decorate(Decoration::ArrayStride)->addExtraOperand(stride);
44bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  auto StructTy = m->getStructType(ArrTy);
45bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  StructTy->decorate(Decoration::BufferBlock);
46bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  StructTy->memberDecorate(0, Decoration::Offset)->addExtraOperand(0);
47bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
48bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  auto StructPtrTy = m->getPointerType(StorageClass::Uniform, StructTy);
49bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
50bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  VariableInst *bufferVar = b.MakeVariable(StructPtrTy, StorageClass::Uniform);
51bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  bufferVar->decorate(Decoration::DescriptorSet)->addExtraOperand(0);
52bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  bufferVar->decorate(Decoration::Binding)->addExtraOperand(binding);
53bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  m->addVariable(bufferVar);
54bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
55bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  return bufferVar;
56bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni}
57bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
58bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Nibool AddWrapper(const char *name, const uint32_t signature,
59bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni                const uint32_t numInput, Builder &b, Module *m) {
60bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  FunctionDefinition *kernel = m->lookupFunctionDefinitionByName(name);
61bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  if (kernel == nullptr) {
62bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    // In the metadata for RenderScript LLVM bitcode, the first foreach kernel
63bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    // is always reserved for the root kernel, even though in the most recent RS
64bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    // apps it does not exist. Simply bypass wrapper generation here, and return
65bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    // true for this case.
66bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    // Otherwise, if a non-root kernel function cannot be found, it is a
67bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    // fatal internal error which is really unexpected.
68bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    return (strncmp(name, "root", 4) == 0);
69bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  }
70bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
71bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  // The following three cases are not supported
72bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  if (!MetadataExtractor::hasForEachSignatureKernel(signature)) {
73bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    // Not handling old-style kernel
74bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    return false;
75bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  }
76bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
77bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  if (MetadataExtractor::hasForEachSignatureUsrData(signature)) {
78bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    // Not handling the user argument
79bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    return false;
80bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  }
81bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
82bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  if (MetadataExtractor::hasForEachSignatureCtxt(signature)) {
83bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    // Not handling the context argument
84bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    return false;
85bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  }
86bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
87bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  TypeVoidInst *VoidTy = m->getVoidType();
88bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  TypeFunctionInst *FuncTy = m->getFunctionType(VoidTy, nullptr, 0);
89bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  FunctionDefinition *Func =
90bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni      b.MakeFunctionDefinition(VoidTy, FunctionControl::None, FuncTy);
91bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  m->addFunctionDefinition(Func);
92bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
93bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  Block *Blk = b.MakeBlock();
94bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  Func->addBlock(Blk);
95bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
96bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  Blk->addInstruction(b.MakeLabel());
97bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
98bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  TypeIntInst *UIntTy = m->getUnsignedIntType(32);
99bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
100bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  Instruction *XValue = nullptr;
101bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  Instruction *YValue = nullptr;
102bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  Instruction *ZValue = nullptr;
103bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  Instruction *Index = nullptr;
104bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  VariableInst *InvocationId = nullptr;
105bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  VariableInst *NumWorkgroups = nullptr;
106bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
107bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  if (MetadataExtractor::hasForEachSignatureIn(signature) ||
108bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni      MetadataExtractor::hasForEachSignatureOut(signature) ||
109bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni      MetadataExtractor::hasForEachSignatureX(signature) ||
110bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni      MetadataExtractor::hasForEachSignatureY(signature) ||
111bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni      MetadataExtractor::hasForEachSignatureZ(signature)) {
112bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    TypeVectorInst *V3UIntTy = m->getVectorType(UIntTy, 3);
113bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    InvocationId = m->getInvocationId();
114bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    auto IID = b.MakeLoad(V3UIntTy, InvocationId);
115bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    Blk->addInstruction(IID);
116bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
117bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    XValue = b.MakeCompositeExtract(UIntTy, IID, {0});
118bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    Blk->addInstruction(XValue);
119bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
120bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    YValue = b.MakeCompositeExtract(UIntTy, IID, {1});
121bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    Blk->addInstruction(YValue);
122bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
123bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    ZValue = b.MakeCompositeExtract(UIntTy, IID, {2});
124bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    Blk->addInstruction(ZValue);
125bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
126bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    // TODO: Use SpecConstant for workgroup size
127bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    auto ConstOne = m->getConstant(UIntTy, 1U);
128bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    auto GroupSize =
129bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni        m->getConstantComposite(V3UIntTy, ConstOne, ConstOne, ConstOne);
130bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
131bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    auto GroupSizeX = b.MakeCompositeExtract(UIntTy, GroupSize, {0});
132bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    Blk->addInstruction(GroupSizeX);
133bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
134bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    auto GroupSizeY = b.MakeCompositeExtract(UIntTy, GroupSize, {1});
135bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    Blk->addInstruction(GroupSizeY);
136bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
137bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    NumWorkgroups = m->getNumWorkgroups();
138bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    auto NumGroup = b.MakeLoad(V3UIntTy, NumWorkgroups);
139bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    Blk->addInstruction(NumGroup);
140bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
141bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    auto NumGroupX = b.MakeCompositeExtract(UIntTy, NumGroup, {0});
142bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    Blk->addInstruction(NumGroupX);
143bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
144bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    auto NumGroupY = b.MakeCompositeExtract(UIntTy, NumGroup, {1});
145bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    Blk->addInstruction(NumGroupY);
146bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
147bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    auto GlobalSizeX = b.MakeIMul(UIntTy, GroupSizeX, NumGroupX);
148bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    Blk->addInstruction(GlobalSizeX);
149bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
150bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    auto GlobalSizeY = b.MakeIMul(UIntTy, GroupSizeY, NumGroupY);
151bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    Blk->addInstruction(GlobalSizeY);
152bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
153bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    auto RowsAlongZ = b.MakeIMul(UIntTy, GlobalSizeY, ZValue);
154bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    Blk->addInstruction(RowsAlongZ);
155bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
156bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    auto NumRows = b.MakeIAdd(UIntTy, YValue, RowsAlongZ);
157bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    Blk->addInstruction(NumRows);
158bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
159bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    auto NumCellsFromYZ = b.MakeIMul(UIntTy, GlobalSizeX, NumRows);
160bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    Blk->addInstruction(NumCellsFromYZ);
161bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
162bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    Index = b.MakeIAdd(UIntTy, NumCellsFromYZ, XValue);
163bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    Blk->addInstruction(Index);
164bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  }
165bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
166bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  std::vector<IdRef> inputs;
167bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
168bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  ConstantInst *ConstZero = m->getConstant(UIntTy, 0);
169bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
170bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  for (uint32_t i = 0; i < numInput; i++) {
171bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    FunctionParameterInst *param = kernel->getParameter(i);
172bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    Instruction *elementType = param->mResultType.mInstruction;
173bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    VariableInst *inputBuffer = AddBuffer(elementType, i + 2, b, m);
174bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
175bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    TypePointerInst *PtrTy =
176bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni        m->getPointerType(StorageClass::Function, elementType);
177bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    AccessChainInst *Ptr =
178bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni        b.MakeAccessChain(PtrTy, inputBuffer, {ConstZero, Index});
179bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    Blk->addInstruction(Ptr);
180bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
181bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    Instruction *input = b.MakeLoad(elementType, Ptr);
182bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    Blk->addInstruction(input);
183bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
184bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    inputs.push_back(IdRef(input));
185bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  }
186bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
187bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  // TODO: Convert from unsigned int to signed int if that is what the kernel
188bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  // function takes for the coordinate parameters
189bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  if (MetadataExtractor::hasForEachSignatureX(signature)) {
190bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    inputs.push_back(XValue);
191bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    if (MetadataExtractor::hasForEachSignatureY(signature)) {
192bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni      inputs.push_back(YValue);
193bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni      if (MetadataExtractor::hasForEachSignatureZ(signature)) {
194bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni        inputs.push_back(ZValue);
195bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni      }
196bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    }
197bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  }
198bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
199bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  auto resultType = kernel->getReturnType();
200bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  auto kernelCall =
201bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni      b.MakeFunctionCall(resultType, kernel->getInstruction(), inputs);
202bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  Blk->addInstruction(kernelCall);
203bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
204bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  if (MetadataExtractor::hasForEachSignatureOut(signature)) {
205bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    VariableInst *OutputBuffer = AddBuffer(resultType, 1, b, m);
206bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    auto resultPtrType = m->getPointerType(StorageClass::Function, resultType);
207bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    AccessChainInst *OutPtr =
208bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni        b.MakeAccessChain(resultPtrType, OutputBuffer, {ConstZero, Index});
209bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    Blk->addInstruction(OutPtr);
210bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    Blk->addInstruction(b.MakeStore(OutPtr, kernelCall));
211bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  }
212bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
213bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  Blk->addInstruction(b.MakeReturn());
214bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
215bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  std::string wrapperName("entry_");
216bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  wrapperName.append(name);
217bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
218bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  EntryPointDefinition *entry = b.MakeEntryPointDefinition(
219bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni      ExecutionModel::GLCompute, Func, wrapperName.c_str());
220bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
221bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  entry->setLocalSize(1, 1, 1);
222bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
223bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  if (Index != nullptr) {
224bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    entry->addToInterface(InvocationId);
225bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    entry->addToInterface(NumWorkgroups);
226bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  }
227bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
228bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  m->addEntryPoint(entry);
229bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
230bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  return true;
231bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni}
232bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
233bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Nibool DecorateGlobalBuffer(llvm::Module &LM, Builder &b, Module *m) {
234bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  Instruction *inst = m->lookupByName("__GPUBlock");
235bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  if (inst == nullptr) {
236bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    return true;
237bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  }
238bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
239bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  VariableInst *bufferVar = static_cast<VariableInst *>(inst);
240bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  bufferVar->decorate(Decoration::DescriptorSet)->addExtraOperand(0);
241bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  bufferVar->decorate(Decoration::Binding)->addExtraOperand(0);
242bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
243bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  TypePointerInst *StructPtrTy =
244bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni      static_cast<TypePointerInst *>(bufferVar->mResultType.mInstruction);
245bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  TypeStructInst *StructTy =
246bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni      static_cast<TypeStructInst *>(StructPtrTy->mOperand2.mInstruction);
247bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  StructTy->decorate(Decoration::BufferBlock);
248bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
249bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  // Decorate each member with proper offsets
250bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
251bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  const auto GlobalsB = LM.globals().begin();
252bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  const auto GlobalsE = LM.globals().end();
253bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  const auto Found =
254bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni      std::find_if(GlobalsB, GlobalsE, [](const llvm::GlobalVariable &GV) {
255bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni        return GV.getName() == "__GPUBlock";
256bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni      });
257bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
258bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  if (Found == GlobalsE) {
259bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    return true; // GPUBlock not found - not an error by itself.
260bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  }
261bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
262bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  const llvm::GlobalVariable &G = *Found;
263bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
264bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  bool IsCorrectTy = false;
265bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  if (const auto *LPtrTy = llvm::dyn_cast<llvm::PointerType>(G.getType())) {
266bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    if (auto *LStructTy =
267bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni            llvm::dyn_cast<llvm::StructType>(LPtrTy->getElementType())) {
268bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni      IsCorrectTy = true;
269bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
270bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni      const auto &DLayout = LM.getDataLayout();
271bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni      const auto *SLayout = DLayout.getStructLayout(LStructTy);
272bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni      assert(SLayout);
273bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni      if (SLayout == nullptr) {
274bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni        std::cerr << "struct layout is null" << std::endl;
275bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni        return false;
276bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni      }
277bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni      for (uint32_t i = 0, e = LStructTy->getNumElements(); i != e; ++i) {
278bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni        auto decor = StructTy->memberDecorate(i, Decoration::Offset);
279bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni        if (!decor) {
280bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni          std::cerr << "failed creating member decoration for field " << i
281bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni                    << std::endl;
282bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni          return false;
283bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni        }
284eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni        const uint32_t offset = (uint32_t)SLayout->getElementOffset(i);
285eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni        decor->addExtraOperand(offset);
286bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni      }
287bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    }
288bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  }
289bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
290bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  if (!IsCorrectTy) {
291bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    return false;
292bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  }
293bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
294bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  llvm::SmallVector<rs2spirv::RSAllocationInfo, 2> RSAllocs;
295bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  if (!getRSAllocationInfo(LM, RSAllocs)) {
296bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    // llvm::errs() << "Extracting rs_allocation info failed\n";
297bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    return true;
298bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  }
299bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
300bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  // TODO: clean up the binding number assignment
301bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  size_t BindingNum = 3;
302bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  for (const auto &A : RSAllocs) {
303bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    Instruction *inst = m->lookupByName(A.VarName.c_str());
304bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    if (inst == nullptr) {
305bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni      return false;
306bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    }
307bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    VariableInst *bufferVar = static_cast<VariableInst *>(inst);
308bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    bufferVar->decorate(Decoration::DescriptorSet)->addExtraOperand(0);
309bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    bufferVar->decorate(Decoration::Binding)->addExtraOperand(BindingNum++);
310bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  }
311bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
312bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  return true;
313bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni}
314bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
315bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Nivoid AddHeader(Module *m) {
316bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  m->addCapability(Capability::Shader);
317bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  // TODO: avoid duplicated capability
318bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  // m->addCapability(Capability::Addresses);
319bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  m->setMemoryModel(AddressingModel::Physical32, MemoryModel::GLSL450);
320bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
321bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  m->addSource(SourceLanguage::GLSL, 450);
322bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  m->addSourceExtension("GL_ARB_separate_shader_objects");
323bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  m->addSourceExtension("GL_ARB_shading_language_420pack");
324bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  m->addSourceExtension("GL_GOOGLE_cpp_style_line_directive");
325bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  m->addSourceExtension("GL_GOOGLE_include_directive");
326bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni}
327bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
328bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ninamespace {
329bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
330bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Niclass StorageClassVisitor : public DoNothingVisitor {
331bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Nipublic:
332bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  void visit(TypePointerInst *inst) override {
333bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    matchAndReplace(inst->mOperand1);
334bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  }
335bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
336bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  void visit(TypeForwardPointerInst *inst) override {
337bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    matchAndReplace(inst->mOperand2);
338bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  }
339bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
340bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  void visit(VariableInst *inst) override { matchAndReplace(inst->mOperand1); }
341bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
342bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Niprivate:
343bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  void matchAndReplace(StorageClass &storage) {
344bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    if (storage == StorageClass::Function) {
345bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni      storage = StorageClass::Uniform;
346bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    }
347bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  }
348bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni};
349bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
350bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Nivoid FixGlobalStorageClass(Module *m) {
351bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  StorageClassVisitor v;
352bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  m->getGlobalSection()->accept(&v);
353bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni}
354bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
355bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni} // anonymous namespace
356bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
357eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Nibool AddWrappers(llvm::Module &LM,
3583f30b6202dd5ad6ff66959131d216405850ed152Yang Ni                 android::spirit::Module *m) {
359eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  rs2spirv::Context &Ctxt = rs2spirv::Context::getInstance();
360eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  const bcinfo::MetadataExtractor &metadata = Ctxt.getMetadata();
361bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  android::spirit::Builder b;
362bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
363bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  m->setBuilder(&b);
364bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
3653f30b6202dd5ad6ff66959131d216405850ed152Yang Ni  FixGlobalStorageClass(m);
366bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
3673f30b6202dd5ad6ff66959131d216405850ed152Yang Ni  AddHeader(m);
368bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
3693f30b6202dd5ad6ff66959131d216405850ed152Yang Ni  DecorateGlobalBuffer(LM, b, m);
370bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
371bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  const size_t numKernel = metadata.getExportForEachSignatureCount();
372bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  const char **kernelName = metadata.getExportForEachNameList();
373bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  const uint32_t *kernelSigature = metadata.getExportForEachSignatureList();
374bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  const uint32_t *inputCount = metadata.getExportForEachInputCountList();
375bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
376bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  for (size_t i = 0; i < numKernel; i++) {
377bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    bool success =
3783f30b6202dd5ad6ff66959131d216405850ed152Yang Ni        AddWrapper(kernelName[i], kernelSigature[i], inputCount[i], b, m);
379bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    if (!success) {
3803f30b6202dd5ad6ff66959131d216405850ed152Yang Ni      return false;
381bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni    }
382bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  }
383bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
384bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni  m->consolidateAnnotations();
3853f30b6202dd5ad6ff66959131d216405850ed152Yang Ni  return true;
3863f30b6202dd5ad6ff66959131d216405850ed152Yang Ni}
3879d73d08c545462e706ef6951952acff94c37605aI-Jui (Ray) Sung
3883f30b6202dd5ad6ff66959131d216405850ed152Yang Niclass WrapperPass : public Pass {
3893f30b6202dd5ad6ff66959131d216405850ed152Yang Nipublic:
390eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  WrapperPass(const llvm::Module &LM) : mLLVMModule(const_cast<llvm::Module&>(LM)) {}
3913f30b6202dd5ad6ff66959131d216405850ed152Yang Ni
3923f30b6202dd5ad6ff66959131d216405850ed152Yang Ni  Module *run(Module *m, int *error) override {
393eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni    bool success = AddWrappers(mLLVMModule, m);
3943f30b6202dd5ad6ff66959131d216405850ed152Yang Ni    if (error) {
3953f30b6202dd5ad6ff66959131d216405850ed152Yang Ni      *error = success ? 0 : -1;
3963f30b6202dd5ad6ff66959131d216405850ed152Yang Ni    }
3973f30b6202dd5ad6ff66959131d216405850ed152Yang Ni    return m;
3989d73d08c545462e706ef6951952acff94c37605aI-Jui (Ray) Sung  }
3999d73d08c545462e706ef6951952acff94c37605aI-Jui (Ray) Sung
4003f30b6202dd5ad6ff66959131d216405850ed152Yang Niprivate:
4013f30b6202dd5ad6ff66959131d216405850ed152Yang Ni  llvm::Module &mLLVMModule;
4023f30b6202dd5ad6ff66959131d216405850ed152Yang Ni};
4039d73d08c545462e706ef6951952acff94c37605aI-Jui (Ray) Sung
4043f30b6202dd5ad6ff66959131d216405850ed152Yang Ni} // namespace spirit
4053f30b6202dd5ad6ff66959131d216405850ed152Yang Ni} // namespace android
4069d73d08c545462e706ef6951952acff94c37605aI-Jui (Ray) Sung
4073f30b6202dd5ad6ff66959131d216405850ed152Yang Ninamespace rs2spirv {
408bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
409eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Niandroid::spirit::Pass* CreateWrapperPass(const llvm::Module &LLVMModule) {
410eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  return new android::spirit::WrapperPass(LLVMModule);
411bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni}
412bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni
413bf22a8ab4f46a98ee37f95fc0402744132cc3ed2Yang Ni} // namespace rs2spirv
414