1/*
2 * Copyright 2017, 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#ifndef RS2SPIRV_CONTEXT_H
18#define RS2SPIRV_CONTEXT_H
19
20#include "RSAllocationUtils.h"
21#include "bcinfo/MetadataExtractor.h"
22
23#include "llvm/ADT/StringMap.h"
24#include "llvm/ADT/StringRef.h"
25
26#include <limits>
27#include <stdint.h>
28#include <vector>
29
30// Declare a friend relationship in a class with a test. Used rather that
31// FRIEND_TEST to avoid globally importing gtest/gtest.h into the main
32// RSoV header files.
33#ifdef __HOST__
34#define RSOV_FRIEND_TEST(test_set_name, individual_test)                       \
35  friend class test_set_name##_##individual_test##_Test
36#else
37#define RSOV_FRIEND_TEST(test_set_name, individual_test)
38#endif // __HOST__
39
40namespace bcinfo {
41class MetadataExtractor;
42}
43
44namespace llvm {
45class Module;
46}
47
48namespace rs2spirv {
49
50// A singleton that keeps state during the compilation from RS LLVM bitcode to
51// SPIR-V, which provides quick lookup of metadata and shares information
52// between the passes.
53class Context {
54  RSOV_FRIEND_TEST(ContextTest, testInitialize);
55
56public:
57  static Context &getInstance();
58
59  Context();
60
61  // Initialize the internal data struture such as the slot number lookup table,
62  // etc.
63  bool Initialize(std::unique_ptr<bcinfo::MetadataExtractor> ME);
64
65  // Returns the total number of exported variables
66  uint32_t getNumExportVar() const { return mExportVarIndices.size(); }
67
68  // Adds the mapping from the slot number of an exported variable to the index
69  // of its field in the global buffer
70  void addExportVarIndex(uint32_t slot, uint32_t index) {
71    mExportVarIndices[slot] = index;
72  }
73
74  // Adds the mapping from the name of an exported variable to the index of its
75  // field in the global buffer
76  void addExportVarIndex(const char *varName, uint32_t index) {
77    const uint32_t slot = getSlotForExportVar(varName);
78    if (slot == std::numeric_limits<uint32_t>::max()) {
79      assert(0 && "Invalid name for an exported variable");
80      return;
81    }
82    addExportVarIndex(slot, index);
83  }
84
85  // Given the slot number of an exported variable, returns the index of its
86  // field in the global buffer
87  uint32_t getExportVarIndex(uint32_t slot) const {
88    return mExportVarIndices[slot];
89  }
90
91  // Returns the total number of foreach kernels
92  uint32_t getNumForEachKernel() const { return mForEachNameToSlot.size(); }
93
94  // Checks if a name refers to a foreach kernel function
95  bool isForEachKernel(llvm::StringRef name) const {
96    return mForEachNameToSlot.count(name) != 0;
97  }
98
99  const bcinfo::MetadataExtractor &getMetadata() const { return *mMetadata; }
100
101  llvm::SmallVectorImpl<RSAllocationInfo> &getGlobalAllocs() {
102    return mGlobalAllocs;
103  }
104
105private:
106  uint32_t getSlotForExportVar(const char *varName) {
107    const llvm::StringRef strVarName(varName);
108    auto it = mVarNameToSlot.find(strVarName);
109    if (it == mVarNameToSlot.end()) {
110      return std::numeric_limits<uint32_t>::max();
111    }
112    return it->second;
113  }
114
115  bool mInitialized;
116  // RenderScript metadata embedded in the input LLVM Moduel
117  std::unique_ptr<bcinfo::MetadataExtractor> mMetadata;
118  // A map from exported variable names to their slot numbers
119  llvm::StringMap<uint32_t> mVarNameToSlot;
120  // A map from exported foreach kernel names to their slot numbers
121  llvm::StringMap<uint32_t> mForEachNameToSlot;
122  // These are the indices for each exported variable in the global buffer
123  std::vector<uint32_t> mExportVarIndices;
124  // For Global Allocations; carries global variable -> metadata offset
125  // mapping from an LLVM pass to a SPIRIT pass
126  llvm::SmallVector<RSAllocationInfo, 8> mGlobalAllocs;
127};
128
129} // namespace rs2spirv
130
131#endif // RS2SPIRV_CONTEXT_H
132