186a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines/*
286a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines * Copyright 2012, The Android Open Source Project
386a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines *
486a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines * Licensed under the Apache License, Version 2.0 (the "License");
586a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines * you may not use this file except in compliance with the License.
686a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines * You may obtain a copy of the License at
786a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines *
886a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines *     http://www.apache.org/licenses/LICENSE-2.0
986a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines *
1086a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines * Unless required by applicable law or agreed to in writing, software
1186a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines * distributed under the License is distributed on an "AS IS" BASIS,
1286a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1386a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines * See the License for the specific language governing permissions and
1486a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines * limitations under the License.
1586a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines */
1686a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines
1786a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines#include "bcc/Assert.h"
18fb81ec1a875d13d9750006313b9123903336101dStephen Hines#include "bcc/Config/Config.h"
1986a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines#include "bcc/Renderscript/RSTransforms.h"
2057fd9f882f3359be4201c42b02aebf785d311df2David Gross#include "bcc/Renderscript/RSUtils.h"
21fb81ec1a875d13d9750006313b9123903336101dStephen Hines#include "bcc/Support/Log.h"
22fb81ec1a875d13d9750006313b9123903336101dStephen Hines#include "bcinfo/MetadataExtractor.h"
23fb81ec1a875d13d9750006313b9123903336101dStephen Hines#include "rsDefines.h"
2486a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines
2586a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines#include <cstdlib>
260116d8b4247829adfb64b9cb7992eb783a54abd5Stephen Hines#include <vector>
2786a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines
28b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines#include <llvm/IR/DerivedTypes.h>
29b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines#include <llvm/IR/Function.h>
30b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines#include <llvm/IR/Instructions.h>
31b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines#include <llvm/IR/IRBuilder.h>
32b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines#include <llvm/IR/Module.h>
3386a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines#include <llvm/Pass.h>
3486a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines#include <llvm/Support/raw_ostream.h>
35b730e239619a546d93e5926ea92d698ab77ec7f6Stephen Hines#include <llvm/IR/Type.h>
3686a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines
3786a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hinesusing namespace bcc;
3886a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines
3986a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hinesnamespace {
4086a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines
412d201e547f1d32140ff8ead1818c169f441cf5fbStephen Hines/* RSEmbedInfoPass - This pass operates on the entire module and embeds a
422d201e547f1d32140ff8ead1818c169f441cf5fbStephen Hines * string constaining relevant metadata directly as a global variable.
432d201e547f1d32140ff8ead1818c169f441cf5fbStephen Hines * This information does not need to be consistent across Android releases,
442d201e547f1d32140ff8ead1818c169f441cf5fbStephen Hines * because the standalone compiler + compatibility driver or system driver
452d201e547f1d32140ff8ead1818c169f441cf5fbStephen Hines * will be using the same format (i.e. bcc_compat + libRSSupport.so or
462d201e547f1d32140ff8ead1818c169f441cf5fbStephen Hines * bcc + libRSCpuRef are always paired together for installation).
4786a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines */
4886a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hinesclass RSEmbedInfoPass : public llvm::ModulePass {
4986a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hinesprivate:
5086a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines  static char ID;
5186a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines
5286a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines  llvm::Module *M;
5386a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines  llvm::LLVMContext *C;
5486a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines
5586a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hinespublic:
561253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines  RSEmbedInfoPass()
5786a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines      : ModulePass(ID),
58900c6c1f08f7c572125d7d39abe0f0f9eafbfa14Chris Wailes        M(nullptr) {
5986a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines  }
6086a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines
61c754d49ee856be620e041348a9f2b3d5610a5a26Stephen Hines  virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
62c754d49ee856be620e041348a9f2b3d5610a5a26Stephen Hines    AU.setPreservesAll();
63c754d49ee856be620e041348a9f2b3d5610a5a26Stephen Hines  }
64c754d49ee856be620e041348a9f2b3d5610a5a26Stephen Hines
651253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines  static std::string getRSInfoString(const llvm::Module *module) {
6686a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines    std::string str;
6786a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines    llvm::raw_string_ostream s(str);
681253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines    bcinfo::MetadataExtractor me(module);
691253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines    if (!me.extract()) {
701253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines      bccAssert(false && "Could not extract RS metadata for module!");
711253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines      return std::string("");
721253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines    }
731253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines
741253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines    size_t exportVarCount = me.getExportVarCount();
751253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines    size_t exportFuncCount = me.getExportFuncCount();
761253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines    size_t exportForEachCount = me.getExportForEachSignatureCount();
774e7a50685ae18a24087f6f2a51c604e71fab69e2Matt Wala    size_t exportReduceCount = me.getExportReduceCount();
781253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines    size_t objectSlotCount = me.getObjectSlotCount();
79a99ef646b808e99cf870a8663170a1162851a42fPirama Arumuga Nainar    size_t pragmaCount = me.getPragmaCount();
801253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines    const char **exportVarNameList = me.getExportVarNameList();
811253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines    const char **exportFuncNameList = me.getExportFuncNameList();
821253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines    const char **exportForEachNameList = me.getExportForEachNameList();
831253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines    const uint32_t *exportForEachSignatureList =
841253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines        me.getExportForEachSignatureList();
85a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross    const bcinfo::MetadataExtractor::Reduce *exportReduceList =
86a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross        me.getExportReduceList();
871253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines    const uint32_t *objectSlotList = me.getObjectSlotList();
88a99ef646b808e99cf870a8663170a1162851a42fPirama Arumuga Nainar    const char **pragmaKeyList = me.getPragmaKeyList();
89a99ef646b808e99cf870a8663170a1162851a42fPirama Arumuga Nainar    const char **pragmaValueList = me.getPragmaValueList();
909fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    bool isThreadable = me.isThreadable();
9151ee77bd31e7d8ca6c89e37b5806c8fc2afcf0dcPirama Arumuga Nainar    const char *buildChecksum = me.getBuildChecksum();
9251ee77bd31e7d8ca6c89e37b5806c8fc2afcf0dcPirama Arumuga Nainar
931253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines    size_t i;
9486a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines
9579e1a05f704ada1bb12749fe3f8b9b69309be9e5David Gross    // We use a simple text format here that the compatibility library
9679e1a05f704ada1bb12749fe3f8b9b69309be9e5David Gross    // can easily parse. Each section starts out with its name
9779e1a05f704ada1bb12749fe3f8b9b69309be9e5David Gross    // followed by a count.  The count denotes the number of lines to
98a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross    // parse for that particular category. Variables and Functions
99a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross    // merely put the appropriate identifier on the line. ForEach
100a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross    // kernels have the encoded int signature, followed by a hyphen
101a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross    // followed by the identifier (function to look up). General
102a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross    // reduce kernels have the encoded int signature, followed by a
103a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross    // hyphen followed by the accumulator data size, followed by a
104a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross    // hyphen followed by the identifier (reduction name); and then
105a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross    // for each possible constituent function, a hyphen followed by
106a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross    // the identifier (function name) -- in the case where the
107a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross    // function is omitted, "." is used in place of the identifier.
108a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross    // Object Slots are just listed as one integer per line.
10979e1a05f704ada1bb12749fe3f8b9b69309be9e5David Gross
1101253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines    s << "exportVarCount: " << exportVarCount << "\n";
1111253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines    for (i = 0; i < exportVarCount; ++i) {
1121253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines      s << exportVarNameList[i] << "\n";
11386a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines    }
11486a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines
1151253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines    s << "exportFuncCount: " << exportFuncCount << "\n";
1161253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines    for (i = 0; i < exportFuncCount; ++i) {
1171253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines      s << exportFuncNameList[i] << "\n";
11886a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines    }
11986a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines
1201253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines    s << "exportForEachCount: " << exportForEachCount << "\n";
1211253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines    for (i = 0; i < exportForEachCount; ++i) {
1221253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines      s << exportForEachSignatureList[i] << " - "
1231253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines        << exportForEachNameList[i] << "\n";
12486a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines    }
12586a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines
1264e7a50685ae18a24087f6f2a51c604e71fab69e2Matt Wala    s << "exportReduceCount: " << exportReduceCount << "\n";
127a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross    auto reduceFnName = [](const char *Name) { return Name ? Name : "."; };
1284e7a50685ae18a24087f6f2a51c604e71fab69e2Matt Wala    for (i = 0; i < exportReduceCount; ++i) {
129a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross      const bcinfo::MetadataExtractor::Reduce &reduce = exportReduceList[i];
130a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross      s << reduce.mSignature << " - "
131a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross        << reduce.mAccumulatorDataSize << " - "
132a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross        << reduce.mReduceName << " - "
133a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross        << reduceFnName(reduce.mInitializerName) << " - "
134a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross        << reduceFnName(reduce.mAccumulatorName) << " - "
135a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross        << ((reduce.mCombinerName != nullptr)
136a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross            ? reduce.mCombinerName
137a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross            : nameReduceCombinerFromAccumulator(reduce.mAccumulatorName)) << " - "
138a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross        << reduceFnName(reduce.mOutConverterName) << " - "
139a48ea364652efcf947dd33c8a6ba893e9c00dd6aDavid Gross        << reduceFnName(reduce.mHalterName)
14079e1a05f704ada1bb12749fe3f8b9b69309be9e5David Gross        << "\n";
14179e1a05f704ada1bb12749fe3f8b9b69309be9e5David Gross    }
14279e1a05f704ada1bb12749fe3f8b9b69309be9e5David Gross
1431253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines    s << "objectSlotCount: " << objectSlotCount << "\n";
1441253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines    for (i = 0; i < objectSlotCount; ++i) {
1451253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines      s << objectSlotList[i] << "\n";
14686a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines    }
14786a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines
148a99ef646b808e99cf870a8663170a1162851a42fPirama Arumuga Nainar    s << "pragmaCount: " << pragmaCount << "\n";
149a99ef646b808e99cf870a8663170a1162851a42fPirama Arumuga Nainar    for (i = 0; i < pragmaCount; ++i) {
150a99ef646b808e99cf870a8663170a1162851a42fPirama Arumuga Nainar      s << pragmaKeyList[i] << " - "
151a99ef646b808e99cf870a8663170a1162851a42fPirama Arumuga Nainar        << pragmaValueList[i] << "\n";
152a99ef646b808e99cf870a8663170a1162851a42fPirama Arumuga Nainar    }
1539fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    s << "isThreadable: " << ((isThreadable) ? "yes" : "no") << "\n";
154a99ef646b808e99cf870a8663170a1162851a42fPirama Arumuga Nainar
155e1c7d298e3e38ffff294ce57c37ab43827a67ee5Stephen Hines    if (buildChecksum != nullptr && buildChecksum[0]) {
15651ee77bd31e7d8ca6c89e37b5806c8fc2afcf0dcPirama Arumuga Nainar      s << "buildChecksum: " << buildChecksum << "\n";
15751ee77bd31e7d8ca6c89e37b5806c8fc2afcf0dcPirama Arumuga Nainar    }
15851ee77bd31e7d8ca6c89e37b5806c8fc2afcf0dcPirama Arumuga Nainar
15986a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines    s.flush();
1602d201e547f1d32140ff8ead1818c169f441cf5fbStephen Hines    return str;
1612d201e547f1d32140ff8ead1818c169f441cf5fbStephen Hines  }
1622d201e547f1d32140ff8ead1818c169f441cf5fbStephen Hines
1632d201e547f1d32140ff8ead1818c169f441cf5fbStephen Hines  virtual bool runOnModule(llvm::Module &M) {
1642d201e547f1d32140ff8ead1818c169f441cf5fbStephen Hines    this->M = &M;
1652d201e547f1d32140ff8ead1818c169f441cf5fbStephen Hines    C = &M.getContext();
16686a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines
16786a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines    // Embed this as the global variable .rs.info so that it will be
16886a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines    // accessible from the shared object later.
1692d201e547f1d32140ff8ead1818c169f441cf5fbStephen Hines    llvm::Constant *Init = llvm::ConstantDataArray::getString(*C,
1701253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines                                                              getRSInfoString(&M));
17186a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines    llvm::GlobalVariable *InfoGV =
17286a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines        new llvm::GlobalVariable(M, Init->getType(), true,
17386a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines                                 llvm::GlobalValue::ExternalLinkage, Init,
174fb81ec1a875d13d9750006313b9123903336101dStephen Hines                                 kRsInfo);
17586a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines    (void) InfoGV;
17686a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines
17786a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines    return true;
17886a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines  }
17986a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines
18086a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines  virtual const char *getPassName() const {
18186a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines    return "Embed Renderscript Info";
18286a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines  }
18386a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines
18486a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines};  // end RSEmbedInfoPass
18586a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines
18686a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines}  // end anonymous namespace
18786a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines
18886a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hineschar RSEmbedInfoPass::ID = 0;
18986a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines
19086a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hinesnamespace bcc {
19186a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines
19286a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hinesllvm::ModulePass *
1931253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen HinescreateRSEmbedInfoPass() {
1941253c195dd7911ad91bd66790f03e4c2f8888ad2Stephen Hines  return new RSEmbedInfoPass();
19586a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines}
19686a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines
19786a0b797c221d4c3373dc10c8229b75b6747f6e7Stephen Hines}  // end namespace bcc
198