From 8c81a20ace8c65d0a9d58b9cf333049a2bc0383a Mon Sep 17 00:00:00 2001
From: ReinUsesLisp <reinuseslisp@airmail.cc>
Date: Mon, 10 May 2021 19:32:10 -0300
Subject: glasm: Ensure reg alloc order across compilers on GLASM

Use a struct constructor to serialize register allocation arguments to
ensure registers are allocated in the same order regardless of the
compiler used.

The A and B functions can be called in any order when passed as
arguments to "foo":

  foo(A(), B())

But the order is guaranteed for curly-braced constructor calls in
classes:

  Foo{A(), B()}

Use this to get consistent behavior.
---
 src/shader_recompiler/backend/glasm/emit_glasm.cpp | 25 ++++++++++++----------
 1 file changed, 14 insertions(+), 11 deletions(-)

(limited to 'src/shader_recompiler/backend/glasm/emit_glasm.cpp')

diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp
index c90b80e48b..047b2f89cc 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp
@@ -128,24 +128,27 @@ auto Arg(EmitContext& ctx, const IR::Value& arg) {
     }
 }
 
-template <auto func, bool is_first_arg_inst, typename... Args>
-void InvokeCall(EmitContext& ctx, IR::Inst* inst, Args&&... args) {
-    if constexpr (is_first_arg_inst) {
-        func(ctx, *inst, args.Extract()...);
-    } else {
-        func(ctx, args.Extract()...);
+template <auto func, bool is_first_arg_inst>
+struct InvokeCall {
+    template <typename... Args>
+    InvokeCall(EmitContext& ctx, IR::Inst* inst, Args&&... args) {
+        if constexpr (is_first_arg_inst) {
+            func(ctx, *inst, args.Extract()...);
+        } else {
+            func(ctx, args.Extract()...);
+        }
     }
-}
+};
 
 template <auto func, bool is_first_arg_inst, size_t... I>
 void Invoke(EmitContext& ctx, IR::Inst* inst, std::index_sequence<I...>) {
     using Traits = FuncTraits<decltype(func)>;
     if constexpr (is_first_arg_inst) {
-        InvokeCall<func, is_first_arg_inst>(
-            ctx, inst, Arg<typename Traits::template ArgType<I + 2>>(ctx, inst->Arg(I))...);
+        InvokeCall<func, is_first_arg_inst>{
+            ctx, inst, Arg<typename Traits::template ArgType<I + 2>>(ctx, inst->Arg(I))...};
     } else {
-        InvokeCall<func, is_first_arg_inst>(
-            ctx, inst, Arg<typename Traits::template ArgType<I + 1>>(ctx, inst->Arg(I))...);
+        InvokeCall<func, is_first_arg_inst>{
+            ctx, inst, Arg<typename Traits::template ArgType<I + 1>>(ctx, inst->Arg(I))...};
     }
 }
 
-- 
cgit v1.2.3-70-g09d2