cleanup. delete vaarg stuff. Smuggle format string in Info and flags

This commit is contained in:
Frodo Baggins 2024-10-05 11:48:11 -07:00
parent 6b830f641c
commit e69b2d410c
12 changed files with 52 additions and 160 deletions

View file

@ -49,9 +49,7 @@ void EmitPrologue(EmitContext& ctx);
void EmitEpilogue(EmitContext& ctx);
void EmitDiscard(EmitContext& ctx);
void EmitDiscardCond(EmitContext& ctx, Id condition);
void EmitVaArg(EmitContext& ctx, IR::Inst* inst, Id arg, Id next);
Id EmitStringLiteral(EmitContext& ctx, IR::Inst* inst);
void EmitDebugPrint(EmitContext& ctx, IR::Inst* inst, Id fmt);
void EmitDebugPrint(EmitContext& ctx, IR::Inst* inst, Id arg0, Id arg1, Id arg2, Id arg3, Id arg4);
void EmitBarrier(EmitContext& ctx);
void EmitWorkgroupMemoryBarrier(EmitContext& ctx);
void EmitDeviceMemoryBarrier(EmitContext& ctx);

View file

@ -55,45 +55,15 @@ void EmitEndPrimitive(EmitContext& ctx, const IR::Value& stream) {
throw NotImplementedException("Geometry streams");
}
static bool isEmptyInst(IR::Value val) {
if (auto* inst = val.TryInstRecursive()) {
return inst->GetOpcode() == IR::Opcode::Void;
}
return false;
}
void EmitDebugPrint(EmitContext& ctx, IR::Inst* inst, Id arg0, Id arg1, Id arg2, Id arg3, Id arg4) {
DebugPrintFlags flags = inst->Flags<DebugPrintFlags>();
const std::string& format_string = ctx.info.string_pool[flags.string_idx];
Id fmt = ctx.String(format_string);
void EmitVaArg(EmitContext& ctx, IR::Inst* inst, Id arg, Id next) {
IR::Value next_val = inst->Arg(1);
u32 va_arglist_idx;
if (isEmptyInst(next_val)) {
va_arglist_idx = ctx.va_arg_lists.size();
ctx.va_arg_lists.emplace_back();
} else {
va_arglist_idx = next_val.Inst()->Flags<VariadicArgInfo>().va_arg_idx;
}
ctx.va_arg_lists[va_arglist_idx].push_back(arg);
auto va_info = inst->Flags<VariadicArgInfo>();
va_info.va_arg_idx.Assign(va_arglist_idx);
inst->SetFlags(va_info);
}
Id EmitStringLiteral(EmitContext& ctx, IR::Inst* inst) {
// ctx.
return ctx.String(inst->StringLiteral());
}
void EmitDebugPrint(EmitContext& ctx, IR::Inst* inst, Id fmt) {
IR::Value arglist = inst->Arg(1);
boost::container::small_vector<Id, 4> fmt_arg_operands;
if (!isEmptyInst(arglist)) {
u32 va_arglist_idx = arglist.Inst()->Flags<VariadicArgInfo>().va_arg_idx;
const auto& va_arglist = ctx.va_arg_lists[va_arglist_idx];
// reverse the order
std::copy(va_arglist.rbegin(), va_arglist.rend(), std::back_inserter(fmt_arg_operands));
}
ctx.OpDebugPrintf(fmt, fmt_arg_operands);
std::array<Id, 5> fmt_args = {arg0, arg1, arg2, arg3, arg4};
const std::span<Id> fmt_args_span =
std::span<Id>(fmt_args.begin(), fmt_args.begin() + flags.num_args);
ctx.OpDebugPrintf(fmt, fmt_args_span);
}
} // namespace Shader::Backend::SPIRV

View file

@ -644,7 +644,7 @@ private:
}
case StatementType::SetVariable: {
ensure_block();
IR::IREmitter ir{*current_block};
IR::IREmitter ir{*current_block, info};
ir.SetGotoVariable(stmt.id, VisitExpr(ir, *stmt.op));
break;
}
@ -653,7 +653,7 @@ private:
IR::Block* const merge_block{MergeBlock(parent, stmt)};
// Implement if header block
IR::IREmitter ir{*current_block};
IR::IREmitter ir{*current_block, info};
const IR::U1 cond{ir.ConditionRef(VisitExpr(ir, *stmt.cond))};
const size_t if_node_index{syntax_list.size()};
@ -703,7 +703,7 @@ private:
Visit(stmt, merge_block, continue_block);
// The continue block is located at the end of the loop
IR::IREmitter ir{*continue_block};
IR::IREmitter ir{*continue_block, info};
const IR::U1 cond{ir.ConditionRef(VisitExpr(ir, *stmt.cond))};
IR::Block* const body_block{syntax_list.at(body_block_index).data.block};
@ -739,7 +739,7 @@ private:
ensure_block();
IR::Block* const skip_block{MergeBlock(parent, stmt)};
IR::IREmitter ir{*current_block};
IR::IREmitter ir{*current_block, info};
const IR::U1 cond{ir.ConditionRef(VisitExpr(ir, *stmt.cond))};
current_block->AddBranch(break_block);
current_block->AddBranch(skip_block);
@ -759,7 +759,7 @@ private:
case StatementType::Return: {
ensure_block();
IR::Block* return_block{block_pool.Create(inst_pool)};
IR::IREmitter{*return_block}.Epilogue();
IR::IREmitter{*return_block, info}.Epilogue();
current_block->AddBranch(return_block);
auto& merge{syntax_list.emplace_back()};
@ -773,7 +773,7 @@ private:
case StatementType::Kill: {
ensure_block();
IR::Block* demote_block{MergeBlock(parent, stmt)};
IR::IREmitter{*current_block}.Discard();
IR::IREmitter{*current_block, info}.Discard();
current_block->AddBranch(demote_block);
current_block = demote_block;

View file

@ -19,7 +19,8 @@ namespace Shader::Gcn {
Translator::Translator(IR::Block* block_, Info& info_, const RuntimeInfo& runtime_info_,
const Profile& profile_)
: ir{*block_, block_->begin()}, info{info_}, runtime_info{runtime_info_}, profile{profile_} {}
: ir{*block_, block_->begin(), info_}, info{info_}, runtime_info{runtime_info_},
profile{profile_} {}
void Translator::EmitPrologue() {
ir.Prologue();

View file

@ -179,6 +179,9 @@ struct Info {
std::span<const u32> user_data;
Stage stage;
using StringPool = boost::container::small_vector<std::string, 4>;
StringPool string_pool;
u64 pgm_hash{};
VAddr pgm_base;
bool has_storage_images{};

View file

@ -1,10 +1,10 @@
#include "common/bit_field.h"
#include "src/common/enum.h"
#include "src/common/types.h"
#pragma once
union VariadicArgInfo {
union DebugPrintFlags {
u32 raw;
BitField<0, 12, u32> va_arg_idx;
BitField<0, 16, u32> string_idx;
BitField<16, 16, u32> num_args;
};

View file

@ -1,15 +1,13 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <array>
#include <bit>
#include <iterator>
#include <source_location>
#include <boost/container/small_vector.hpp>
#include "common/assert.h"
#include "shader_recompiler/exception.h"
#include "shader_recompiler/ir/debug_print.h"
#include "shader_recompiler/ir/ir_emitter.h"
#include "shader_recompiler/ir/opcodes.h"
#include "shader_recompiler/ir/value.h"
namespace Shader::IR {
@ -1558,72 +1556,27 @@ void IREmitter::ImageWrite(const Value& handle, const Value& coords, const Value
Inst(Opcode::ImageWrite, Flags{info}, handle, coords, color);
}
Value IREmitter::VaArg(Value arg, Value next) {
return Inst(Opcode::VaArg, arg, next);
}
Value IREmitter::StringLiteral(std::string_view s) {
Value val = Inst(Opcode::StringLiteral);
val.Inst()->SetStringLiteral(s);
return val;
}
void IREmitter::DebugPrint(std::string_view format, boost::container::small_vector<Value, 4> args,
void IREmitter::DebugPrint(std::string_view format,
boost::container::small_vector<Value, 5> format_args,
bool infer_specifiers) {
auto infer_specifier = [&](IR::Value arg) -> const char* {
switch (arg.Type()) {
case Shader::IR::Type::U1:
case Shader::IR::Type::U8:
case Shader::IR::Type::U16:
case Shader::IR::Type::U32:
return "%u";
case Shader::IR::Type::U64:
return "%lu";
case Shader::IR::Type::F16:
case Shader::IR::Type::F32:
case Shader::IR::Type::F64:
return "%lf";
case Shader::IR::Type::U32x2:
return "%v2u";
case Shader::IR::Type::U32x3:
return "%v3u";
case Shader::IR::Type::U32x4:
return "%v4u";
case Shader::IR::Type::F16x2:
case Shader::IR::Type::F32x2:
case Shader::IR::Type::F64x2:
return "%v2f";
case Shader::IR::Type::F16x3:
case Shader::IR::Type::F32x3:
case Shader::IR::Type::F64x3:
return "%v3f";
case Shader::IR::Type::F16x4:
case Shader::IR::Type::F32x4:
case Shader::IR::Type::F64x4:
return "%v4f";
case Shader::IR::Type::Void:
case Shader::IR::Type::Opaque:
case Shader::IR::Type::ScalarReg:
case Shader::IR::Type::VectorReg:
case Shader::IR::Type::Attribute:
case Shader::IR::Type::SystemValue:
UNREACHABLE();
}
};
std::array<Value, 5> args;
if (infer_specifiers) {
UNREACHABLE();
// need to fmt the format string with dynamic sized array of format spec strings
// could use param pack for this function, but less flexible
for (int i = 0; i < format_args.size(); i++) {
args[i] = format_args[i];
}
Value arg_list = Inst(Opcode::Void);
for (Value arg : args) {
arg_list = VaArg(arg, arg_list);
for (int i = format_args.size(); i < 4; i++) {
args[i] = Inst(Opcode::Void);
}
Value string_val = StringLiteral(format);
Inst(Opcode::DebugPrint, string_val, arg_list);
Value val = Inst(Opcode::DebugPrint, args[0], args[1], args[2], args[3], args[4]);
DebugPrintFlags flags;
flags.string_idx.Assign(info.string_pool.size());
info.string_pool.emplace_back(format);
flags.num_args.Assign(format_args.size());
val.Inst()->SetFlags<DebugPrintFlags>(flags);
}
} // namespace Shader::IR

View file

@ -8,6 +8,7 @@
#include <type_traits>
#include <boost/container/small_vector.hpp>
#include "shader_recompiler/info.h"
#include "shader_recompiler/ir/attribute.h"
#include "shader_recompiler/ir/basic_block.h"
#include "shader_recompiler/ir/condition.h"
@ -17,9 +18,10 @@ namespace Shader::IR {
class IREmitter {
public:
explicit IREmitter(Block& block_) : block{&block_}, insertion_point{block->end()} {}
explicit IREmitter(Block& block_, Block::iterator insertion_point_)
: block{&block_}, insertion_point{insertion_point_} {}
explicit IREmitter(Block& block_, Shader::Info& info_)
: block{&block_}, insertion_point{block->end()}, info(info_) {}
explicit IREmitter(Block& block_, Block::iterator insertion_point_, Shader::Info& info_)
: block{&block_}, insertion_point{insertion_point_}, info(info_) {}
Block* block;
@ -45,11 +47,7 @@ public:
void Epilogue();
void Discard();
void Discard(const U1& cond);
Value VaArg(Value arg, Value next);
Value StringLiteral(std::string_view s);
void DebugPrint(std::string_view format, boost::container::small_vector<Value, 4> args,
void DebugPrint(std::string_view format, boost::container::small_vector<Value, 5> args,
bool infer_specifiers = false);
void Barrier();
@ -320,6 +318,7 @@ public:
private:
IR::Block::iterator insertion_point;
Shader::Info& info;
template <typename T = Value, typename... Args>
T Inst(Opcode op, Args... args) {

View file

@ -14,8 +14,6 @@ namespace Shader::IR {
Inst::Inst(IR::Opcode op_, u32 flags_) noexcept : op{op_}, flags{flags_} {
if (op == Opcode::Phi) {
std::construct_at(&phi_args);
} else if (op == Opcode::StringLiteral) {
std::construct_at(&string_literal);
} else {
std::construct_at(&args);
}
@ -24,8 +22,6 @@ Inst::Inst(IR::Opcode op_, u32 flags_) noexcept : op{op_}, flags{flags_} {
Inst::Inst(const Inst& base) : op{base.op}, flags{base.flags} {
if (base.op == Opcode::Phi) {
throw NotImplementedException("Copying phi node");
} else if (base.op == Opcode::StringLiteral) {
std::construct_at(&string_literal, base.string_literal);
} else {
std::construct_at(&args);
const size_t num_args{base.NumArgs()};
@ -38,8 +34,6 @@ Inst::Inst(const Inst& base) : op{base.op}, flags{base.flags} {
Inst::~Inst() {
if (op == Opcode::Phi) {
std::destroy_at(&phi_args);
} else if (op == Opcode::StringLiteral) {
std::destroy_at(&string_literal);
} else {
std::destroy_at(&args);
}
@ -107,9 +101,6 @@ bool Inst::AreAllArgsImmediates() const {
if (op == Opcode::Phi) {
UNREACHABLE_MSG("Testing for all arguments are immediates on phi instruction");
}
if (op == Opcode::StringLiteral) {
UNREACHABLE_MSG("Testing for all arguments are immediates on StringLiteral instruction");
}
return std::all_of(args.begin(), args.begin() + NumArgs(),
[](const IR::Value& value) { return value.IsImmediate(); });
}
@ -131,8 +122,6 @@ void Inst::SetArg(size_t index, Value value) {
}
if (op == Opcode::Phi) {
phi_args[index].second = value;
} else if (op == Opcode::StringLiteral) {
UNREACHABLE_MSG("SetArg on StringLiteral instruction");
} else {
args[index] = value;
}
@ -169,8 +158,6 @@ void Inst::ClearArgs() {
}
}
phi_args.clear();
} else if (op == Opcode::StringLiteral) {
string_literal.clear();
} else {
for (auto& value : args) {
if (!value.IsImmediate()) {
@ -196,9 +183,6 @@ void Inst::ReplaceOpcode(IR::Opcode opcode) {
if (opcode == IR::Opcode::Phi) {
UNREACHABLE_MSG("Cannot transition into Phi");
}
if (op == IR::Opcode::StringLiteral || opcode == IR::Opcode::StringLiteral) {
UNREACHABLE_MSG("Cannot transition to or from StringLiteral");
}
if (op == Opcode::Phi) {
// Transition out of phi arguments into non-phi
std::destroy_at(&phi_args);

View file

@ -14,9 +14,7 @@ OPCODE(Prologue, Void,
OPCODE(Epilogue, Void, )
OPCODE(Discard, Void, )
OPCODE(DiscardCond, Void, U1, )
OPCODE(DebugPrint, Void, Opaque, Opaque, )
OPCODE(VaArg, Opaque, Opaque, Opaque )
OPCODE(StringLiteral, Opaque, )
OPCODE(DebugPrint, Void, Opaque, Opaque, Opaque, Opaque, Opaque, )
// Constant memory operations
OPCODE(ReadConst, U32, U32x2, U32, )

View file

@ -377,7 +377,7 @@ void PatchBufferInstruction(IR::Block& block, IR::Inst& inst, Info& info,
const auto inst_info = inst.Flags<IR::BufferInstInfo>();
// Replace handle with binding index in buffer resource list.
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst), info};
inst.SetArg(0, ir.Imm32(binding));
ASSERT(!buffer.add_tid_enable);
@ -436,7 +436,7 @@ void PatchTextureBufferInstruction(IR::Block& block, IR::Inst& inst, Info& info,
});
// Replace handle with binding index in texture buffer resource list.
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst), info};
inst.SetArg(0, ir.Imm32(binding));
ASSERT(!buffer.swizzle_enable && !buffer.add_tid_enable);
}
@ -534,7 +534,7 @@ void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descrip
image_binding |= (sampler_binding << 16);
// Patch image handle
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst), info};
inst.SetArg(0, ir.Imm32(image_binding));
// No need to patch coordinates if we are just querying.
@ -667,7 +667,7 @@ void PatchDataRingInstruction(IR::Block& block, IR::Inst& inst, Info& info,
}();
// Patch instruction.
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst), info};
inst.SetArg(0, ir.Imm32(gds_addr >> 2));
inst.SetArg(1, ir.Imm32(binding));
}

View file

@ -6,11 +6,9 @@
#include <array>
#include <bit>
#include <cstring>
#include <string_view>
#include <type_traits>
#include <utility>
#include <boost/container/small_vector.hpp>
#include <boost/container/string.hpp>
#include <boost/intrusive/list.hpp>
#include "common/assert.h"
@ -148,7 +146,6 @@ public:
if (op == IR::Opcode::Phi) {
return phi_args[index].second;
} else {
ASSERT(op != IR::Opcode::StringLiteral);
return args[index];
}
}
@ -161,16 +158,6 @@ public:
/// Add phi operand to a phi instruction.
void AddPhiOperand(Block* predecessor, const Value& value);
[[nodiscard]] std::string_view StringLiteral() const {
ASSERT(op == IR::Opcode::StringLiteral);
return string_literal;
}
void SetStringLiteral(std::string_view s) noexcept {
ASSERT(op == IR::Opcode::StringLiteral);
string_literal = s;
}
void Invalidate();
void ClearArgs();
@ -220,7 +207,6 @@ private:
NonTriviallyDummy dummy{};
boost::container::small_vector<std::pair<Block*, Value>, 2> phi_args;
std::array<Value, 5> args;
boost::container::string string_literal;
};
};
static_assert(sizeof(Inst) <= 128, "Inst size unintentionally increased");