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