blob: 02814eddf59bbd0b57506bb67c4e1b0c9ddab599 [file] [log] [blame]
// Copyright (C) 2016 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef SPV_MANAGER_H_
#define SPV_MANAGER_H_
#define DEBUG
#include "third_party/khronos/SPIRV-Tools/external/spirv-headers/include/spirv/1.1/spirv.hpp"
#include "third_party/khronos/SPIRV-Tools/include/spirv-tools/libspirv.h"
#include "third_party/khronos/SPIRV-Tools/source/assembly_grammar.h"
#include "third_party/khronos/SPIRV-Tools/source/opcode.h"
#include "third_party/khronos/SPIRV-Tools/source/operand.h"
#include "third_party/khronos/SPIRV-Tools/source/opt/def_use_manager.h"
#include "third_party/khronos/SPIRV-Tools/source/opt/libspirv.hpp"
#include "third_party/khronos/SPIRV-Tools/source/opt/make_unique.h"
#include "third_party/khronos/SPIRV-Tools/source/opt/reflect.h"
#include "third_party/khronos/SPIRV-Tools/source/opt/type_manager.h"
#include "third_party/khronos/SPIRV-Tools/source/opt/types.h"
#include "NameManager.h"
#include "common.h"
#include "libmanager.h"
#include <stdint.h>
#include <cstring>
#include <map>
#include <set>
#include <string>
#include <utility> // std::pair, std::make_pair
#include <vector>
namespace spvmanager {
using spvtools::ir::Module;
using spvtools::ir::Instruction;
using spvtools::ir::BasicBlock;
using spvtools::ir::Function;
using spvtools::opt::analysis::TypeManager;
using spvtools::opt::analysis::Type;
using spvtools::opt::analysis::DefUseManager;
#define MANAGER_SPV_ENV SPV_ENV_UNIVERSAL_1_1 // from spirv-tools
typedef std::map<uint32_t, uint32_t> map_uint;
typedef std::pair<uint32_t, uint32_t> name_type;
class SpvManager {
public:
SpvManager(const std::vector<uint32_t>& spv_binary) {
globals.result.name = "gapid_result";
globals.sampler.name = "gapid_sampler";
globals.coordinate.name = "gapid_coor";
globals.curr_step.name = "gapid_curr_step";
globals.uint_type_id = 0;
globals.void_id = 0;
globals.label_print_id = 0;
std::unique_ptr<spv_context_t> context(spvContextCreate(MANAGER_SPV_ENV));
grammar.reset(new libspirv::AssemblyGrammar(context.get()));
// init module
spvtools::SpvTools spv(MANAGER_SPV_ENV);
module = spv.BuildModule(spv_binary);
type_mgr.reset(new TypeManager(*module));
def_use_mgr.reset(new DefUseManager(module.get()));
name_mgr.reset(new namemanager::NameManager(module.get()));
}
void addOutputForInputs(std::string = "_out");
void mapDeclarationNames(std::string = "x");
void makeSpvDebuggable();
std::vector<unsigned int> getSpvBinary();
debug_instructions_t* getDebugInstructions();
private:
struct Variable {
std::string name;
uint32_t ref_id = 0;
uint32_t type_id = 0;
};
struct ManagerGlobals {
Variable result;
Variable sampler;
Variable coordinate;
Variable curr_step;
uint32_t uint_type_id;
uint32_t void_id;
uint32_t label_print_id;
};
std::unique_ptr<libspirv::AssemblyGrammar> grammar;
std::unique_ptr<Module> module;
std::unique_ptr<TypeManager> type_mgr;
std::unique_ptr<DefUseManager> def_use_mgr;
std::unique_ptr<namemanager::NameManager> name_mgr;
ManagerGlobals globals;
// accumulator
std::vector<std::unique_ptr<Instruction>> curr_block_insts;
map_uint typeid_to_printid;
map_uint consts;
std::vector<spvtools::ir::Operand> makeOperands(
spv_opcode_desc&, std::initializer_list<std::initializer_list<uint32_t>>&, const char* = nullptr);
std::unique_ptr<Instruction> makeInstruction(SpvOp_, uint32_t, uint32_t,
std::initializer_list<std::initializer_list<uint32_t>>,
const char* = nullptr);
std::unique_ptr<BasicBlock> makeBasicBlock(uint32_t, Function*,
std::vector<std::unique_ptr<Instruction>>&);
uint32_t addName(const char*);
uint32_t addConstant(uint32_t, std::initializer_list<uint32_t>);
uint32_t addTypeInst(SpvOp_, std::initializer_list<std::initializer_list<uint32_t>>, uint32_t = 0);
void addVariable(uint32_t, uint32_t, spv::StorageClass);
void addGlobalVariable(spv::StorageClass, Variable*);
uint32_t addFunction(const char*, uint32_t, uint32_t);
uint32_t collectInstWithResult(SpvOp_, std::initializer_list<std::initializer_list<uint32_t>> = {{}},
uint32_t = 0);
void collectInstWithoutResult(SpvOp_, std::initializer_list<std::initializer_list<uint32_t>> = {{}},
uint32_t = 0);
uint32_t collectCompositeConstruct(std::initializer_list<std::initializer_list<uint32_t>>, uint32_t);
void collectCondition(uint32_t, uint32_t);
uint32_t collectTypeConversion(name_type, uint32_t);
void collectPrintCall(name_type, uint32_t = 0);
void collectPrintChain(name_type);
void declareDebugVariables();
void declarePrints();
void setStepVariable();
void insertPrintCallsIntoFunctions();
void moveCollectedBlockInsts(BasicBlock::iterator&);
void insertPrintCallsIntoBlock(BasicBlock&);
uint32_t insertPrintDeclaration(uint32_t);
uint32_t getVariableTypeId(uint32_t);
uint32_t getTypeToConvert(const Type*);
uint32_t getArrayLength(const Type*);
const Type* getPointeeIfPointer(uint32_t);
uint32_t getPrintFunction(uint32_t);
bool isConvertedType(const Type*);
bool isDebugFunction(Function&);
bool isDebugInstruction(Instruction*);
bool isArgStoreInst(BasicBlock::iterator, BasicBlock::iterator);
bool isBuiltInDecoration(const Instruction&) const;
bool isInputVariable(const Instruction&) const;
uint32_t getConstId(uint32_t);
uint32_t getUnique();
void appendDebugInstruction(std::vector<instruction_t>*, Instruction*);
};
} // namespace spvmanager
#endif // SPV_MANAGER_H_