From 01cfaf0286da8412d26e7ec5e0fe2b4a74baa595 Mon Sep 17 00:00:00 2001
From: MerryMage <MerryMage@users.noreply.github.com>
Date: Fri, 5 Aug 2016 14:09:10 +0100
Subject: [PATCH] IR: Properly support Identity in IR::Value

---
 src/frontend/ir/ir.cpp | 50 +++++++++++++++++++++++++++++++++++++++++-
 src/frontend/ir/ir.h   | 39 ++++++--------------------------
 2 files changed, 56 insertions(+), 33 deletions(-)

diff --git a/src/frontend/ir/ir.cpp b/src/frontend/ir/ir.cpp
index d8b6ec61..c81b5118 100644
--- a/src/frontend/ir/ir.cpp
+++ b/src/frontend/ir/ir.cpp
@@ -52,8 +52,56 @@ const char* GetNameOf(Opcode op) {
 
 // Value class member definitions
 
+bool Value::IsImmediate() const {
+    if (type == Type::Opaque)
+        return inner.inst->GetOpcode() == Opcode::Identity ? inner.inst->GetArg(0).IsImmediate() : false;
+    return true;
+}
+
+bool Value::IsEmpty() const {
+    return type == Type::Void;
+}
+
 Type Value::GetType() const {
-    return IsImmediate() ? type : inner.inst->GetType();
+    if (type == Type::Opaque) {
+        if (inner.inst->GetOpcode() == Opcode::Identity) {
+            return inner.inst->GetArg(0).GetType();
+        } else {
+            return inner.inst->GetType();
+        }
+    }
+    return type;
+}
+
+Arm::Reg Value::GetRegRef() const {
+    DEBUG_ASSERT(type == Type::RegRef);
+    return inner.imm_regref;
+}
+
+Inst* Value::GetInst() const {
+    DEBUG_ASSERT(type == Type::Opaque);
+    return inner.inst;
+}
+
+bool Value::GetU1() const {
+    if (type == Type::Opaque && inner.inst->GetOpcode() == Opcode::Identity)
+        return inner.inst->GetArg(0).GetU1();
+    DEBUG_ASSERT(type == Type::U1);
+    return inner.imm_u1;
+}
+
+u8 Value::GetU8() const {
+    if (type == Type::Opaque && inner.inst->GetOpcode() == Opcode::Identity)
+        return inner.inst->GetArg(0).GetU8();
+    DEBUG_ASSERT(type == Type::U8);
+    return inner.imm_u8;
+}
+
+u32 Value::GetU32() const {
+    if (type == Type::Opaque && inner.inst->GetOpcode() == Opcode::Identity)
+        return inner.inst->GetArg(0).GetU32();
+    DEBUG_ASSERT(type == Type::U32);
+    return inner.imm_u32;
 }
 
 // Inst class member definitions
diff --git a/src/frontend/ir/ir.h b/src/frontend/ir/ir.h
index f661abca..c9871da5 100644
--- a/src/frontend/ir/ir.h
+++ b/src/frontend/ir/ir.h
@@ -84,40 +84,15 @@ public:
         inner.imm_u32 = value;
     }
 
-    bool IsEmpty() const {
-        return type == Type::Void;
-    }
-
-    bool IsImmediate() const {
-        return type != Type::Opaque;
-    }
-
+    bool IsEmpty() const;
+    bool IsImmediate() const;
     Type GetType() const;
 
-    Inst* GetInst() const {
-        DEBUG_ASSERT(type == Type::Opaque);
-        return inner.inst;
-    }
-
-    Arm::Reg GetRegRef() const {
-        DEBUG_ASSERT(type == Type::RegRef);
-        return inner.imm_regref;
-    }
-
-    bool GetU1() const {
-        DEBUG_ASSERT(type == Type::U1);
-        return inner.imm_u1;
-    }
-
-    u8 GetU8() const {
-        DEBUG_ASSERT(type == Type::U8);
-        return inner.imm_u8;
-    }
-
-    u32 GetU32() const {
-        DEBUG_ASSERT(type == Type::U32);
-        return inner.imm_u32;
-    }
+    Inst* GetInst() const;
+    Arm::Reg GetRegRef() const;
+    bool GetU1() const;
+    u8 GetU8() const;
+    u32 GetU32() const;
 
 private:
     Type type;