From e221baccddea3c0802c97e7f6f60c0c3e6a72b60 Mon Sep 17 00:00:00 2001
From: ameerj <52414509+ameerj@users.noreply.github.com>
Date: Fri, 21 May 2021 02:00:12 -0400
Subject: [PATCH] glsl: Reusable typed variables. IADD32

---
 .../backend/glsl/emit_context.h               |  28 ++-
 .../glsl/emit_glsl_context_get_set.cpp        |   4 +-
 .../backend/glsl/emit_glsl_integer.cpp        | 221 ++++++++++++++++++
 .../glsl/emit_glsl_not_implemented.cpp        | 173 --------------
 .../backend/glsl/reg_alloc.cpp                |  52 +++--
 .../backend/glsl/reg_alloc.h                  |  36 ++-
 6 files changed, 311 insertions(+), 203 deletions(-)

diff --git a/src/shader_recompiler/backend/glsl/emit_context.h b/src/shader_recompiler/backend/glsl/emit_context.h
index 8d093a853..81b970c14 100644
--- a/src/shader_recompiler/backend/glsl/emit_context.h
+++ b/src/shader_recompiler/backend/glsl/emit_context.h
@@ -31,9 +31,33 @@ class EmitContext {
 public:
     explicit EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_);
 
+    // template <typename... Args>
+    // void Add(const char* format_str, IR::Inst& inst, Args&&... args) {
+    //     code += fmt::format(format_str, reg_alloc.Define(inst), std::forward<Args>(args)...);
+    //     // TODO: Remove this
+    //     code += '\n';
+    // }
+
     template <typename... Args>
-    void Add(const char* format_str, IR::Inst& inst, Args&&... args) {
-        code += fmt::format(format_str, reg_alloc.Define(inst), std::forward<Args>(args)...);
+    void AddU32(const char* format_str, IR::Inst& inst, Args&&... args) {
+        code +=
+            fmt::format(format_str, reg_alloc.Define(inst, Type::U32), std::forward<Args>(args)...);
+        // TODO: Remove this
+        code += '\n';
+    }
+
+    template <typename... Args>
+    void AddS32(const char* format_str, IR::Inst& inst, Args&&... args) {
+        code +=
+            fmt::format(format_str, reg_alloc.Define(inst, Type::S32), std::forward<Args>(args)...);
+        // TODO: Remove this
+        code += '\n';
+    }
+
+    template <typename... Args>
+    void AddF32(const char* format_str, IR::Inst& inst, Args&&... args) {
+        code +=
+            fmt::format(format_str, reg_alloc.Define(inst, Type::F32), std::forward<Args>(args)...);
         // TODO: Remove this
         code += '\n';
     }
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp
index 73f0faf35..ff04cffd2 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp
@@ -33,8 +33,8 @@ void EmitGetCbufS16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] const IR
 void EmitGetCbufU32(EmitContext& ctx, IR::Inst* inst, const IR::Value& binding,
                     const IR::Value& offset) {
     const auto u32_offset{offset.U32()};
-    ctx.Add("uint {}=floatBitsToUint(cbuf{}[{}][{}]);", *inst, binding.U32(), u32_offset / 16,
-            (u32_offset / 4) % 4);
+    ctx.AddU32("{}=floatBitsToUint(cbuf{}[{}][{}]);", *inst, binding.U32(), u32_offset / 16,
+               (u32_offset / 4) % 4);
 }
 
 void EmitGetCbufF32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] const IR::Value& binding,
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp
index e69de29bb..6977f74f9 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp
@@ -0,0 +1,221 @@
+
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <string_view>
+
+#include "shader_recompiler/backend/glsl/emit_context.h"
+#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
+#include "shader_recompiler/frontend/ir/value.h"
+#include "shader_recompiler/profile.h"
+
+namespace Shader::Backend::GLSL {
+void EmitIAdd32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst* inst,
+                [[maybe_unused]] std::string a, [[maybe_unused]] std::string b) {
+    ctx.AddU32("{}={}+{};", *inst, a, b);
+}
+
+void EmitIAdd64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string a,
+                [[maybe_unused]] std::string b) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitISub32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string a,
+                [[maybe_unused]] std::string b) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitISub64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string a,
+                [[maybe_unused]] std::string b) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitIMul32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string a,
+                [[maybe_unused]] std::string b) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitINeg32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string value) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitINeg64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string value) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitIAbs32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string value) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitIAbs64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string value) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitShiftLeftLogical32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string base,
+                            [[maybe_unused]] std::string shift) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitShiftLeftLogical64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string base,
+                            [[maybe_unused]] std::string shift) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitShiftRightLogical32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string base,
+                             [[maybe_unused]] std::string shift) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitShiftRightLogical64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string base,
+                             [[maybe_unused]] std::string shift) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitShiftRightArithmetic32([[maybe_unused]] EmitContext& ctx,
+                                [[maybe_unused]] std::string base,
+                                [[maybe_unused]] std::string shift) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitShiftRightArithmetic64([[maybe_unused]] EmitContext& ctx,
+                                [[maybe_unused]] std::string base,
+                                [[maybe_unused]] std::string shift) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBitwiseAnd32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst* inst,
+                      [[maybe_unused]] std::string a, [[maybe_unused]] std::string b) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBitwiseOr32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst* inst,
+                     [[maybe_unused]] std::string a, [[maybe_unused]] std::string b) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBitwiseXor32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst* inst,
+                      [[maybe_unused]] std::string a, [[maybe_unused]] std::string b) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBitFieldInsert([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string base,
+                        [[maybe_unused]] std::string insert, [[maybe_unused]] std::string offset,
+                        std::string count) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBitFieldSExtract([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst* inst,
+                          [[maybe_unused]] std::string base, [[maybe_unused]] std::string offset,
+                          std::string count) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBitFieldUExtract([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst* inst,
+                          [[maybe_unused]] std::string base, [[maybe_unused]] std::string offset,
+                          std::string count) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBitReverse32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string value) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBitCount32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string value) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitBitwiseNot32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string value) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitFindSMsb32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string value) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitFindUMsb32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string value) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitSMin32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string a,
+                [[maybe_unused]] std::string b) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitUMin32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string a,
+                [[maybe_unused]] std::string b) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitSMax32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string a,
+                [[maybe_unused]] std::string b) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitUMax32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string a,
+                [[maybe_unused]] std::string b) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitSClamp32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst* inst,
+                  [[maybe_unused]] std::string value, [[maybe_unused]] std::string min,
+                  std::string max) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitUClamp32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst* inst,
+                  [[maybe_unused]] std::string value, [[maybe_unused]] std::string min,
+                  std::string max) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitSLessThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string lhs,
+                   [[maybe_unused]] std::string rhs) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitULessThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string lhs,
+                   [[maybe_unused]] std::string rhs) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitIEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string lhs,
+                [[maybe_unused]] std::string rhs) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitSLessThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string lhs,
+                        [[maybe_unused]] std::string rhs) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitULessThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string lhs,
+                        [[maybe_unused]] std::string rhs) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitSGreaterThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string lhs,
+                      [[maybe_unused]] std::string rhs) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitUGreaterThan([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string lhs,
+                      [[maybe_unused]] std::string rhs) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitINotEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string lhs,
+                   [[maybe_unused]] std::string rhs) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitSGreaterThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string lhs,
+                           [[maybe_unused]] std::string rhs) {
+    throw NotImplementedException("GLSL Instruction");
+}
+
+void EmitUGreaterThanEqual([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string lhs,
+                           [[maybe_unused]] std::string rhs) {
+    throw NotImplementedException("GLSL Instruction");
+}
+} // namespace Shader::Backend::GLSL
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp
index cbac59ff0..f39c1fff0 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp
@@ -979,179 +979,6 @@ void EmitFPIsNan64(EmitContext& ctx, std::string value) {
     NotImplemented();
 }
 
-void EmitIAdd32(EmitContext& ctx, IR::Inst* inst, std::string a, std::string b) {
-    NotImplemented();
-}
-
-void EmitIAdd64(EmitContext& ctx, std::string a, std::string b) {
-    NotImplemented();
-}
-
-void EmitISub32(EmitContext& ctx, std::string a, std::string b) {
-    NotImplemented();
-}
-
-void EmitISub64(EmitContext& ctx, std::string a, std::string b) {
-    NotImplemented();
-}
-
-void EmitIMul32(EmitContext& ctx, std::string a, std::string b) {
-    NotImplemented();
-}
-
-void EmitINeg32(EmitContext& ctx, std::string value) {
-    NotImplemented();
-}
-
-void EmitINeg64(EmitContext& ctx, std::string value) {
-    NotImplemented();
-}
-
-void EmitIAbs32(EmitContext& ctx, std::string value) {
-    NotImplemented();
-}
-
-void EmitIAbs64(EmitContext& ctx, std::string value) {
-    NotImplemented();
-}
-
-void EmitShiftLeftLogical32(EmitContext& ctx, std::string base, std::string shift) {
-    NotImplemented();
-}
-
-void EmitShiftLeftLogical64(EmitContext& ctx, std::string base, std::string shift) {
-    NotImplemented();
-}
-
-void EmitShiftRightLogical32(EmitContext& ctx, std::string base, std::string shift) {
-    NotImplemented();
-}
-
-void EmitShiftRightLogical64(EmitContext& ctx, std::string base, std::string shift) {
-    NotImplemented();
-}
-
-void EmitShiftRightArithmetic32(EmitContext& ctx, std::string base, std::string shift) {
-    NotImplemented();
-}
-
-void EmitShiftRightArithmetic64(EmitContext& ctx, std::string base, std::string shift) {
-    NotImplemented();
-}
-
-void EmitBitwiseAnd32(EmitContext& ctx, IR::Inst* inst, std::string a, std::string b) {
-    NotImplemented();
-}
-
-void EmitBitwiseOr32(EmitContext& ctx, IR::Inst* inst, std::string a, std::string b) {
-    NotImplemented();
-}
-
-void EmitBitwiseXor32(EmitContext& ctx, IR::Inst* inst, std::string a, std::string b) {
-    NotImplemented();
-}
-
-void EmitBitFieldInsert(EmitContext& ctx, std::string base, std::string insert, std::string offset,
-                        std::string count) {
-    NotImplemented();
-}
-
-void EmitBitFieldSExtract(EmitContext& ctx, IR::Inst* inst, std::string base, std::string offset,
-                          std::string count) {
-    NotImplemented();
-}
-
-void EmitBitFieldUExtract(EmitContext& ctx, IR::Inst* inst, std::string base, std::string offset,
-                          std::string count) {
-    NotImplemented();
-}
-
-void EmitBitReverse32(EmitContext& ctx, std::string value) {
-    NotImplemented();
-}
-
-void EmitBitCount32(EmitContext& ctx, std::string value) {
-    NotImplemented();
-}
-
-void EmitBitwiseNot32(EmitContext& ctx, std::string value) {
-    NotImplemented();
-}
-
-void EmitFindSMsb32(EmitContext& ctx, std::string value) {
-    NotImplemented();
-}
-
-void EmitFindUMsb32(EmitContext& ctx, std::string value) {
-    NotImplemented();
-}
-
-void EmitSMin32(EmitContext& ctx, std::string a, std::string b) {
-    NotImplemented();
-}
-
-void EmitUMin32(EmitContext& ctx, std::string a, std::string b) {
-    NotImplemented();
-}
-
-void EmitSMax32(EmitContext& ctx, std::string a, std::string b) {
-    NotImplemented();
-}
-
-void EmitUMax32(EmitContext& ctx, std::string a, std::string b) {
-    NotImplemented();
-}
-
-void EmitSClamp32(EmitContext& ctx, IR::Inst* inst, std::string value, std::string min,
-                  std::string max) {
-    NotImplemented();
-}
-
-void EmitUClamp32(EmitContext& ctx, IR::Inst* inst, std::string value, std::string min,
-                  std::string max) {
-    NotImplemented();
-}
-
-void EmitSLessThan(EmitContext& ctx, std::string lhs, std::string rhs) {
-    NotImplemented();
-}
-
-void EmitULessThan(EmitContext& ctx, std::string lhs, std::string rhs) {
-    NotImplemented();
-}
-
-void EmitIEqual(EmitContext& ctx, std::string lhs, std::string rhs) {
-    NotImplemented();
-}
-
-void EmitSLessThanEqual(EmitContext& ctx, std::string lhs, std::string rhs) {
-    NotImplemented();
-}
-
-void EmitULessThanEqual(EmitContext& ctx, std::string lhs, std::string rhs) {
-    NotImplemented();
-}
-
-void EmitSGreaterThan(EmitContext& ctx, std::string lhs, std::string rhs) {
-    NotImplemented();
-}
-
-void EmitUGreaterThan(EmitContext& ctx, std::string lhs, std::string rhs) {
-    NotImplemented();
-}
-
-void EmitINotEqual(EmitContext& ctx, std::string lhs, std::string rhs) {
-    NotImplemented();
-}
-
-void EmitSGreaterThanEqual(EmitContext& ctx, std::string lhs, std::string rhs) {
-    NotImplemented();
-}
-
-void EmitUGreaterThanEqual(EmitContext& ctx, std::string lhs, std::string rhs) {
-    NotImplemented();
-}
-
 void EmitSharedAtomicIAdd32(EmitContext& ctx, std::string pointer_offset, std::string value) {
     NotImplemented();
 }
diff --git a/src/shader_recompiler/backend/glsl/reg_alloc.cpp b/src/shader_recompiler/backend/glsl/reg_alloc.cpp
index 5fdad5acb..5ad1872db 100644
--- a/src/shader_recompiler/backend/glsl/reg_alloc.cpp
+++ b/src/shader_recompiler/backend/glsl/reg_alloc.cpp
@@ -13,7 +13,6 @@
 #pragma optimize("", off)
 namespace Shader::Backend::GLSL {
 namespace {
-constexpr std::string_view SWIZZLE = "xyzw";
 
 std::string Representation(Id id) {
     if (id.is_condition_code != 0) {
@@ -22,7 +21,6 @@ std::string Representation(Id id) {
     if (id.is_spill != 0) {
         throw NotImplementedException("Spilling");
     }
-    const u32 num_elements{id.num_elements_minus_one + 1};
     const u32 index{static_cast<u32>(id.index)};
     return fmt::format("R{}", index);
 }
@@ -45,10 +43,11 @@ std::string MakeImm(const IR::Value& value) {
 }
 } // Anonymous namespace
 
-std::string RegAlloc::Define(IR::Inst& inst, u32 num_elements, u32 alignment) {
-    const Id id{Alloc(num_elements, alignment)};
+std::string RegAlloc::Define(IR::Inst& inst, Type type) {
+    const Id id{Alloc()};
+    const auto type_str{GetType(type, id.index)};
     inst.SetDefinition<Id>(id);
-    return Representation(id);
+    return type_str + Representation(id);
 }
 
 std::string RegAlloc::Consume(const IR::Value& value) {
@@ -65,20 +64,37 @@ std::string RegAlloc::Consume(IR::Inst& inst) {
     return Representation(inst.Definition<Id>());
 }
 
-Id RegAlloc::Alloc(u32 num_elements, [[maybe_unused]] u32 alignment) {
-    for (size_t reg = 0; reg < NUM_REGS; ++reg) {
-        if (register_use[reg]) {
-            continue;
+std::string RegAlloc::GetType(Type type, u32 index) {
+    if (register_defined[index]) {
+        return "";
+    }
+    register_defined[index] = true;
+    switch (type) {
+    case Type::U32:
+        return "uint ";
+    case Type::S32:
+        return "int ";
+    case Type::F32:
+        return "float ";
+    default:
+        return "";
+    }
+}
+
+Id RegAlloc::Alloc() {
+    if (num_used_registers < NUM_REGS) {
+        for (size_t reg = 0; reg < NUM_REGS; ++reg) {
+            if (register_use[reg]) {
+                continue;
+            }
+            register_use[reg] = true;
+            Id ret{};
+            ret.index.Assign(static_cast<u32>(reg));
+            ret.is_long.Assign(0);
+            ret.is_spill.Assign(0);
+            ret.is_condition_code.Assign(0);
+            return ret;
         }
-        num_used_registers = std::max(num_used_registers, reg + 1);
-        register_use[reg] = true;
-        return Id{
-            .base_element = 0,
-            .num_elements_minus_one = num_elements - 1,
-            .index = static_cast<u32>(reg),
-            .is_spill = 0,
-            .is_condition_code = 0,
-        };
     }
     throw NotImplementedException("Register spilling");
 }
diff --git a/src/shader_recompiler/backend/glsl/reg_alloc.h b/src/shader_recompiler/backend/glsl/reg_alloc.h
index a777cbbd2..9b98aab39 100644
--- a/src/shader_recompiler/backend/glsl/reg_alloc.h
+++ b/src/shader_recompiler/backend/glsl/reg_alloc.h
@@ -6,6 +6,7 @@
 
 #include <bitset>
 
+#include "common/bit_field.h"
 #include "common/common_types.h"
 
 namespace Shader::IR {
@@ -14,18 +15,36 @@ class Value;
 } // namespace Shader::IR
 
 namespace Shader::Backend::GLSL {
+enum class Type : u32 {
+    U32,
+    S32,
+    F32,
+    U64,
+    F64,
+    Void,
+};
 
 struct Id {
-    u32 base_element : 2;
-    u32 num_elements_minus_one : 2;
-    u32 index : 26;
-    u32 is_spill : 1;
-    u32 is_condition_code : 1;
+    union {
+        u32 raw;
+        BitField<0, 29, u32> index;
+        BitField<29, 1, u32> is_long;
+        BitField<30, 1, u32> is_spill;
+        BitField<31, 1, u32> is_condition_code;
+    };
+
+    bool operator==(Id rhs) const noexcept {
+        return raw == rhs.raw;
+    }
+    bool operator!=(Id rhs) const noexcept {
+        return !operator==(rhs);
+    }
 };
+static_assert(sizeof(Id) == sizeof(u32));
 
 class RegAlloc {
 public:
-    std::string Define(IR::Inst& inst, u32 num_elements = 1, u32 alignment = 1);
+    std::string Define(IR::Inst& inst, Type type = Type::Void);
 
     std::string Consume(const IR::Value& value);
 
@@ -40,13 +59,14 @@ private:
     static constexpr size_t NUM_ELEMENTS = 4;
 
     std::string Consume(IR::Inst& inst);
+    std::string GetType(Type type, u32 index);
 
-    Id Alloc(u32 num_elements, u32 alignment);
-
+    Id Alloc();
     void Free(Id id);
 
     size_t num_used_registers{};
     std::bitset<NUM_REGS> register_use{};
+    std::bitset<NUM_REGS> register_defined{};
 };
 
 } // namespace Shader::Backend::GLSL