shader: Initial implementation of an AST

This commit is contained in:
ReinUsesLisp 2021-02-11 16:39:06 -03:00 committed by ameerj
parent 5ee600cf64
commit c4d75e4b78
33 changed files with 1347 additions and 591 deletions

View file

@ -17,6 +17,8 @@ namespace Shader::IR {
Block::Block(ObjectPool<Inst>& inst_pool_, u32 begin, u32 end)
: inst_pool{&inst_pool_}, location_begin{begin}, location_end{end} {}
Block::Block(ObjectPool<Inst>& inst_pool_) : Block{inst_pool_, 0, 0} {}
Block::~Block() = default;
void Block::AppendNewInst(Opcode op, std::initializer_list<Value> args) {
@ -38,8 +40,25 @@ Block::iterator Block::PrependNewInst(iterator insertion_point, Opcode op,
return result_it;
}
void Block::AddImmediatePredecessor(IR::Block* immediate_predecessor) {
imm_predecessors.push_back(immediate_predecessor);
void Block::SetBranches(Condition cond, Block* branch_true_, Block* branch_false_) {
branch_cond = cond;
branch_true = branch_true_;
branch_false = branch_false_;
}
void Block::SetBranch(Block* branch) {
branch_cond = Condition{true};
branch_true = branch;
}
void Block::SetReturn() {
branch_cond = Condition{true};
branch_true = nullptr;
branch_false = nullptr;
}
bool Block::IsVirtual() const noexcept {
return location_begin == location_end;
}
u32 Block::LocationBegin() const noexcept {
@ -58,6 +77,12 @@ const Block::InstructionList& Block::Instructions() const noexcept {
return instructions;
}
void Block::AddImmediatePredecessor(Block* block) {
if (std::ranges::find(imm_predecessors, block) == imm_predecessors.end()) {
imm_predecessors.push_back(block);
}
}
std::span<IR::Block* const> Block::ImmediatePredecessors() const noexcept {
return imm_predecessors;
}
@ -70,8 +95,17 @@ static std::string BlockToIndex(const std::map<const Block*, size_t>& block_to_i
return fmt::format("$<unknown block {:016x}>", reinterpret_cast<u64>(block));
}
static size_t InstIndex(std::map<const Inst*, size_t>& inst_to_index, size_t& inst_index,
const Inst* inst) {
const auto [it, is_inserted]{inst_to_index.emplace(inst, inst_index + 1)};
if (is_inserted) {
++inst_index;
}
return it->second;
}
static std::string ArgToIndex(const std::map<const Block*, size_t>& block_to_index,
const std::map<const Inst*, size_t>& inst_to_index,
std::map<const Inst*, size_t>& inst_to_index, size_t& inst_index,
const Value& arg) {
if (arg.IsEmpty()) {
return "<null>";
@ -80,10 +114,7 @@ static std::string ArgToIndex(const std::map<const Block*, size_t>& block_to_ind
return BlockToIndex(block_to_index, arg.Label());
}
if (!arg.IsImmediate()) {
if (const auto it{inst_to_index.find(arg.Inst())}; it != inst_to_index.end()) {
return fmt::format("%{}", it->second);
}
return fmt::format("%<unknown inst {:016x}>", reinterpret_cast<u64>(arg.Inst()));
return fmt::format("%{}", InstIndex(inst_to_index, inst_index, arg.Inst()));
}
switch (arg.Type()) {
case Type::U1:
@ -125,14 +156,14 @@ std::string DumpBlock(const Block& block, const std::map<const Block*, size_t>&
const Opcode op{inst.Opcode()};
ret += fmt::format("[{:016x}] ", reinterpret_cast<u64>(&inst));
if (TypeOf(op) != Type::Void) {
ret += fmt::format("%{:<5} = {}", inst_index, op);
ret += fmt::format("%{:<5} = {}", InstIndex(inst_to_index, inst_index, &inst), op);
} else {
ret += fmt::format(" {}", op); // '%00000 = ' -> 1 + 5 + 3 = 9 spaces
}
const size_t arg_count{NumArgsOf(op)};
const size_t arg_count{inst.NumArgs()};
for (size_t arg_index = 0; arg_index < arg_count; ++arg_index) {
const Value arg{inst.Arg(arg_index)};
const std::string arg_str{ArgToIndex(block_to_index, inst_to_index, arg)};
const std::string arg_str{ArgToIndex(block_to_index, inst_to_index, inst_index, arg)};
ret += arg_index != 0 ? ", " : " ";
if (op == Opcode::Phi) {
ret += fmt::format("[ {}, {} ]", arg_index,
@ -140,10 +171,12 @@ std::string DumpBlock(const Block& block, const std::map<const Block*, size_t>&
} else {
ret += arg_str;
}
const Type actual_type{arg.Type()};
const Type expected_type{ArgTypeOf(op, arg_index)};
if (!AreTypesCompatible(actual_type, expected_type)) {
ret += fmt::format("<type error: {} != {}>", actual_type, expected_type);
if (op != Opcode::Phi) {
const Type actual_type{arg.Type()};
const Type expected_type{ArgTypeOf(op, arg_index)};
if (!AreTypesCompatible(actual_type, expected_type)) {
ret += fmt::format("<type error: {} != {}>", actual_type, expected_type);
}
}
}
if (TypeOf(op) != Type::Void) {
@ -151,9 +184,6 @@ std::string DumpBlock(const Block& block, const std::map<const Block*, size_t>&
} else {
ret += '\n';
}
inst_to_index.emplace(&inst, inst_index);
++inst_index;
}
return ret;
}