1eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni/*
2eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni * Copyright 2017, The Android Open Source Project
3eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni *
4eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni * Licensed under the Apache License, Version 2.0 (the "License");
5eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni * you may not use this file except in compliance with the License.
6eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni * You may obtain a copy of the License at
7eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni *
8eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni *     http://www.apache.org/licenses/LICENSE-2.0
9eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni *
10eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni * Unless required by applicable law or agreed to in writing, software
11eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni * distributed under the License is distributed on an "AS IS" BASIS,
12eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni * See the License for the specific language governing permissions and
14eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni * limitations under the License.
15eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni */
16eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni
17eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni#ifndef RS2SPIRV_CONTEXT_H
18eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni#define RS2SPIRV_CONTEXT_H
19eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni
20c2f647a6c790cb1f4c86e50506c53cd912e725f6I-Jui (Ray) Sung#include "RSAllocationUtils.h"
21eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni#include "bcinfo/MetadataExtractor.h"
22eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni
23eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni#include "llvm/ADT/StringMap.h"
24eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni#include "llvm/ADT/StringRef.h"
25eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni
26eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni#include <limits>
27bbf0b0eac5b1aa65ded878d80a0adc83e48527c8I-Jui (Ray) Sung#include <stdint.h>
28eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni#include <vector>
29eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni
30eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni// Declare a friend relationship in a class with a test. Used rather that
31eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni// FRIEND_TEST to avoid globally importing gtest/gtest.h into the main
32eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni// RSoV header files.
33eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni#ifdef __HOST__
34bbf0b0eac5b1aa65ded878d80a0adc83e48527c8I-Jui (Ray) Sung#define RSOV_FRIEND_TEST(test_set_name, individual_test)                       \
35bbf0b0eac5b1aa65ded878d80a0adc83e48527c8I-Jui (Ray) Sung  friend class test_set_name##_##individual_test##_Test
36eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni#else
37eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni#define RSOV_FRIEND_TEST(test_set_name, individual_test)
38bbf0b0eac5b1aa65ded878d80a0adc83e48527c8I-Jui (Ray) Sung#endif // __HOST__
39eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni
40eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ninamespace bcinfo {
41eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Niclass MetadataExtractor;
42eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni}
43eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni
44eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ninamespace llvm {
45eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Niclass Module;
46eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni}
47eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni
48eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ninamespace rs2spirv {
49eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni
50eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni// A singleton that keeps state during the compilation from RS LLVM bitcode to
51eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni// SPIR-V, which provides quick lookup of metadata and shares information
52eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni// between the passes.
53eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Niclass Context {
54eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  RSOV_FRIEND_TEST(ContextTest, testInitialize);
55eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni
56eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Nipublic:
57eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  static Context &getInstance();
58eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni
59eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  Context();
60eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni
61eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  // Initialize the internal data struture such as the slot number lookup table,
62eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  // etc.
63bbf0b0eac5b1aa65ded878d80a0adc83e48527c8I-Jui (Ray) Sung  bool Initialize(std::unique_ptr<bcinfo::MetadataExtractor> ME);
64eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni
65eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  // Returns the total number of exported variables
66bbf0b0eac5b1aa65ded878d80a0adc83e48527c8I-Jui (Ray) Sung  uint32_t getNumExportVar() const { return mExportVarIndices.size(); }
67eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni
68eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  // Adds the mapping from the slot number of an exported variable to the index
69eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  // of its field in the global buffer
70eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  void addExportVarIndex(uint32_t slot, uint32_t index) {
71eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni    mExportVarIndices[slot] = index;
72eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  }
73eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni
74eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  // Adds the mapping from the name of an exported variable to the index of its
75eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  // field in the global buffer
76eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  void addExportVarIndex(const char *varName, uint32_t index) {
77eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni    const uint32_t slot = getSlotForExportVar(varName);
78eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni    if (slot == std::numeric_limits<uint32_t>::max()) {
79eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni      assert(0 && "Invalid name for an exported variable");
80eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni      return;
81eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni    }
82eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni    addExportVarIndex(slot, index);
83eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  }
84eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni
85eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  // Given the slot number of an exported variable, returns the index of its
86eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  // field in the global buffer
87eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  uint32_t getExportVarIndex(uint32_t slot) const {
88eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni    return mExportVarIndices[slot];
89eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  }
90eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni
91eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  // Returns the total number of foreach kernels
92bbf0b0eac5b1aa65ded878d80a0adc83e48527c8I-Jui (Ray) Sung  uint32_t getNumForEachKernel() const { return mForEachNameToSlot.size(); }
93eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni
94eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  // Checks if a name refers to a foreach kernel function
95eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  bool isForEachKernel(llvm::StringRef name) const {
96eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni    return mForEachNameToSlot.count(name) != 0;
97eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  }
98eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni
99bbf0b0eac5b1aa65ded878d80a0adc83e48527c8I-Jui (Ray) Sung  const bcinfo::MetadataExtractor &getMetadata() const { return *mMetadata; }
100eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni
101c2f647a6c790cb1f4c86e50506c53cd912e725f6I-Jui (Ray) Sung  llvm::SmallVectorImpl<RSAllocationInfo> &getGlobalAllocs() {
102c2f647a6c790cb1f4c86e50506c53cd912e725f6I-Jui (Ray) Sung    return mGlobalAllocs;
103c2f647a6c790cb1f4c86e50506c53cd912e725f6I-Jui (Ray) Sung  }
104c2f647a6c790cb1f4c86e50506c53cd912e725f6I-Jui (Ray) Sung
105eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Niprivate:
106eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  uint32_t getSlotForExportVar(const char *varName) {
107eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni    const llvm::StringRef strVarName(varName);
108eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni    auto it = mVarNameToSlot.find(strVarName);
109eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni    if (it == mVarNameToSlot.end()) {
110eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni      return std::numeric_limits<uint32_t>::max();
111eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni    }
112eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni    return it->second;
113eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  }
114eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni
115eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  bool mInitialized;
116eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  // RenderScript metadata embedded in the input LLVM Moduel
117eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  std::unique_ptr<bcinfo::MetadataExtractor> mMetadata;
118eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  // A map from exported variable names to their slot numbers
119eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  llvm::StringMap<uint32_t> mVarNameToSlot;
120eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  // A map from exported foreach kernel names to their slot numbers
121eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  llvm::StringMap<uint32_t> mForEachNameToSlot;
122eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  // These are the indices for each exported variable in the global buffer
123eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni  std::vector<uint32_t> mExportVarIndices;
124c2f647a6c790cb1f4c86e50506c53cd912e725f6I-Jui (Ray) Sung  // For Global Allocations; carries global variable -> metadata offset
125c2f647a6c790cb1f4c86e50506c53cd912e725f6I-Jui (Ray) Sung  // mapping from an LLVM pass to a SPIRIT pass
126c2f647a6c790cb1f4c86e50506c53cd912e725f6I-Jui (Ray) Sung  llvm::SmallVector<RSAllocationInfo, 8> mGlobalAllocs;
127eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni};
128eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni
129eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni} // namespace rs2spirv
130eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni
131eb6548743c40f4129ca55a58ff2d5254f22e95e1Yang Ni#endif // RS2SPIRV_CONTEXT_H
132