summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/backend/glasm/emit_glasm.cpp
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2021-05-05 02:19:08 -0300
committerGravatar ameerj2021-07-22 21:51:30 -0400
commitb10cf64c486d8730fcfeb53a333814915b3b5fbe (patch)
tree59cb4f62ac806071e0f0a341589c164017520f3a /src/shader_recompiler/backend/glasm/emit_glasm.cpp
parentshader: ISET.X implementation (diff)
downloadyuzu-b10cf64c486d8730fcfeb53a333814915b3b5fbe.tar.gz
yuzu-b10cf64c486d8730fcfeb53a333814915b3b5fbe.tar.xz
yuzu-b10cf64c486d8730fcfeb53a333814915b3b5fbe.zip
glasm: Add GLASM backend infrastructure
Diffstat (limited to 'src/shader_recompiler/backend/glasm/emit_glasm.cpp')
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm.cpp95
1 files changed, 95 insertions, 0 deletions
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp
new file mode 100644
index 000000000..59d7c0f96
--- /dev/null
+++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp
@@ -0,0 +1,95 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <string>
6#include <tuple>
7
8#include "shader_recompiler/backend/bindings.h"
9#include "shader_recompiler/backend/glasm/emit_context.h"
10#include "shader_recompiler/backend/glasm/emit_glasm.h"
11#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
12#include "shader_recompiler/frontend/ir/program.h"
13#include "shader_recompiler/profile.h"
14
15namespace Shader::Backend::GLASM {
16namespace {
17template <class Func>
18struct FuncTraits {};
19
20template <class ReturnType_, class... Args>
21struct FuncTraits<ReturnType_ (*)(Args...)> {
22 using ReturnType = ReturnType_;
23
24 static constexpr size_t NUM_ARGS = sizeof...(Args);
25
26 template <size_t I>
27 using ArgType = std::tuple_element_t<I, std::tuple<Args...>>;
28};
29
30template <typename ArgType>
31auto Arg(EmitContext& ctx, const IR::Value& arg) {
32 if constexpr (std::is_same_v<ArgType, std::string_view>) {
33 return ctx.reg_alloc.Consume(arg);
34 } else if constexpr (std::is_same_v<ArgType, const IR::Value&>) {
35 return arg;
36 } else if constexpr (std::is_same_v<ArgType, u32>) {
37 return arg.U32();
38 } else if constexpr (std::is_same_v<ArgType, IR::Block*>) {
39 return arg.Label();
40 } else if constexpr (std::is_same_v<ArgType, IR::Attribute>) {
41 return arg.Attribute();
42 } else if constexpr (std::is_same_v<ArgType, IR::Patch>) {
43 return arg.Patch();
44 } else if constexpr (std::is_same_v<ArgType, IR::Reg>) {
45 return arg.Reg();
46 }
47}
48
49template <auto func, bool is_first_arg_inst, size_t... I>
50void Invoke(EmitContext& ctx, IR::Inst* inst, std::index_sequence<I...>) {
51 using Traits = FuncTraits<decltype(func)>;
52 if constexpr (is_first_arg_inst) {
53 func(ctx, inst, Arg<typename Traits::template ArgType<I + 2>>(ctx, inst->Arg(I))...);
54 } else {
55 func(ctx, Arg<typename Traits::template ArgType<I + 1>>(ctx, inst->Arg(I))...);
56 }
57}
58
59template <auto func>
60void Invoke(EmitContext& ctx, IR::Inst* inst) {
61 using Traits = FuncTraits<decltype(func)>;
62 static_assert(Traits::NUM_ARGS >= 1, "Insufficient arguments");
63 if constexpr (Traits::NUM_ARGS == 1) {
64 Invoke<func, false>(ctx, inst, std::make_index_sequence<0>{});
65 } else {
66 using FirstArgType = typename Traits::template ArgType<1>;
67 static constexpr bool is_first_arg_inst = std::is_same_v<FirstArgType, IR::Inst*>;
68 using Indices = std::make_index_sequence<Traits::NUM_ARGS - (is_first_arg_inst ? 2 : 1)>;
69 Invoke<func, is_first_arg_inst>(ctx, inst, Indices{});
70 }
71}
72
73void EmitInst(EmitContext& ctx, IR::Inst* inst) {
74 switch (inst->GetOpcode()) {
75#define OPCODE(name, result_type, ...) \
76 case IR::Opcode::name: \
77 return Invoke<&Emit##name>(ctx, inst);
78#include "shader_recompiler/frontend/ir/opcodes.inc"
79#undef OPCODE
80 }
81 throw LogicError("Invalid opcode {}", inst->GetOpcode());
82}
83} // Anonymous namespace
84
85std::string EmitGLASM(const Profile&, IR::Program& program, Bindings&) {
86 EmitContext ctx;
87 for (IR::Block* const block : program.blocks) {
88 for (IR::Inst& inst : block->Instructions()) {
89 EmitInst(ctx, &inst);
90 }
91 }
92 return ctx.code;
93}
94
95} // namespace Shader::Backend::GLASM