From fa937d4874846e94918b1df83d2b64733121079a Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Fri, 23 Jul 2021 17:26:47 +0200
Subject: [PATCH] Added support for union default initializers (initializing
 the first element) including any necessary padding to reach the right byte
 size. #197

---
 .../cache/fragment-cache-mos6502x.asm         |  31 +++
 .../camelot64/kickc/model/Initializers.java   |   8 +-
 .../kickc/passes/Pass4CodeGeneration.java     |  12 +
 .../kickc/test/TestProgramsFast.java          |  15 +
 src/test/kc/union-4.c                         |  21 ++
 src/test/kc/union-5.c                         |  20 ++
 src/test/kc/union-6.c                         |  16 ++
 src/test/ref/union-4.asm                      |  38 +++
 src/test/ref/union-4.cfg                      |  12 +
 src/test/ref/union-4.log                      | 257 ++++++++++++++++++
 src/test/ref/union-4.sym                      |   6 +
 src/test/ref/union-5.asm                      |  29 ++
 src/test/ref/union-5.cfg                      |  11 +
 src/test/ref/union-5.log                      | 228 ++++++++++++++++
 src/test/ref/union-5.sym                      |   5 +
 src/test/ref/union-6.asm                      |  30 ++
 src/test/ref/union-6.cfg                      |  12 +
 src/test/ref/union-6.log                      | 222 +++++++++++++++
 src/test/ref/union-6.sym                      |   9 +
 19 files changed, 978 insertions(+), 4 deletions(-)
 create mode 100644 src/test/kc/union-4.c
 create mode 100644 src/test/kc/union-5.c
 create mode 100644 src/test/kc/union-6.c
 create mode 100644 src/test/ref/union-4.asm
 create mode 100644 src/test/ref/union-4.cfg
 create mode 100644 src/test/ref/union-4.log
 create mode 100644 src/test/ref/union-4.sym
 create mode 100644 src/test/ref/union-5.asm
 create mode 100644 src/test/ref/union-5.cfg
 create mode 100644 src/test/ref/union-5.log
 create mode 100644 src/test/ref/union-5.sym
 create mode 100644 src/test/ref/union-6.asm
 create mode 100644 src/test/ref/union-6.cfg
 create mode 100644 src/test/ref/union-6.log
 create mode 100644 src/test/ref/union-6.sym

diff --git a/src/main/fragment/cache/fragment-cache-mos6502x.asm b/src/main/fragment/cache/fragment-cache-mos6502x.asm
index 4afcdbfbc..cc6f75509 100644
--- a/src/main/fragment/cache/fragment-cache-mos6502x.asm
+++ b/src/main/fragment/cache/fragment-cache-mos6502x.asm
@@ -15234,3 +15234,34 @@ sta {z1}+2
 lda {z2}+3
 sbc #>{c1}>>$10
 sta {z1}+3
+//FRAGMENT vwuz1=vwuc1_plus_vbuz2
+lda {z2}
+clc
+adc #<{c1}
+sta {z1}
+lda #>{c1}
+adc #0
+sta {z1}+1
+//FRAGMENT vwuz1=vwuc1_plus_vbuaa
+clc
+adc #<{c1}
+sta {z1}
+lda #>{c1}
+adc #0
+sta {z1}+1
+//FRAGMENT vwuz1=vwuc1_plus_vbuxx
+txa
+clc
+adc #<{c1}
+sta {z1}
+lda #>{c1}
+adc #0
+sta {z1}+1
+//FRAGMENT vwuz1=vwuc1_plus_vbuyy
+tya
+clc
+adc #<{c1}
+sta {z1}
+lda #>{c1}
+adc #0
+sta {z1}+1
diff --git a/src/main/java/dk/camelot64/kickc/model/Initializers.java b/src/main/java/dk/camelot64/kickc/model/Initializers.java
index 80549eb4d..6281b9360 100644
--- a/src/main/java/dk/camelot64/kickc/model/Initializers.java
+++ b/src/main/java/dk/camelot64/kickc/model/Initializers.java
@@ -141,11 +141,11 @@ public class Initializers {
       // Recursively cast all sub-elements
       StructDefinition structDefinition = structType.getStructDefinition(program.getScope());
       Collection<Variable> memberDefinitions = structDefinition.getAllVars(false);
-      int size = memberDefinitions.size();
-      if(size != valueList.getList().size()) {
+      int structInitNeedSize = structDefinition.isUnion()? 1 : memberDefinitions.size() ;
+      if(structInitNeedSize != valueList.getList().size()) {
          throw new CompileError(
                "Struct initializer has wrong size (" + valueList.getList().size() + "), " +
-                     "which does not match the number of members in " + structType.getTypeName() + " (" + size + " members).\n" +
+                     "which does not match the number of members in " + structType.getTypeName() + " (" + structInitNeedSize + " members).\n" +
                      " Struct initializer: " + valueList.toString(program),
                source);
       }
@@ -157,7 +157,7 @@ public class Initializers {
       LinkedHashMap<SymbolVariableRef, ConstantValue> constMemberMap = new LinkedHashMap<>();
       Iterator<Variable> memberDefIt = memberDefinitions.iterator();
       Iterator<RValue> valueIt = valueList.getList().iterator();
-      for(int i = 0; i < size; i++) {
+      for(int i = 0; i < structInitNeedSize; i++) {
          Variable memberDef = memberDefIt.next();
          RValue memberValue = valueIt.next();
          RValue constantifiedMemberValue = constantify(memberValue, new ValueTypeSpec(memberDef.getType()), program, source);
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java
index 5504ddf9d..49f6562f3 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java
@@ -653,10 +653,22 @@ public class Pass4CodeGeneration {
          if(value instanceof ConstantStructValue) {
             // Add each struct member recursively
             ConstantStructValue structValue = (ConstantStructValue) value;
+            int size = 0;
             for(SymbolVariableRef memberRef : structValue.getMembers()) {
                ConstantValue memberValue = structValue.getValue(memberRef);
                Variable memberVariable = getScope().getVar(memberRef);
                addChunkData(dataChunk, memberValue, memberVariable.getType(), memberVariable.getArraySpec(), scopeRef);
+               size += SymbolTypeStruct.getMemberSizeBytes(memberVariable.getType(),  memberVariable.getArraySize(), getScope());
+            }
+            // Add padding if this is a union and the first member does not use all bytes
+            final int declaredSize = structValue.getStructType().getSizeBytes();
+            if(size<declaredSize) {
+               long paddingSize = declaredSize - size;
+               // TODO: Use SIZEOF constant
+               ConstantValue paddingSizeVal = new ConstantInteger(paddingSize);
+               String paddingBytesAsm  = AsmFormat.getAsmConstant(program, paddingSizeVal, 99, scopeRef);
+               ConstantValue zeroValue = new ConstantInteger(0l, SymbolType.BYTE);
+               dataChunk.addDataZeroFilled(AsmDataNumeric.Type.BYTE, paddingBytesAsm, (int)paddingSize, getEncoding(zeroValue));
             }
          } else if(value instanceof StructZero) {
             final SymbolTypeStruct typeStruct = ((StructZero) value).getTypeStruct();
diff --git a/src/test/java/dk/camelot64/kickc/test/TestProgramsFast.java b/src/test/java/dk/camelot64/kickc/test/TestProgramsFast.java
index a80aaaab6..c16451a99 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestProgramsFast.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestProgramsFast.java
@@ -2223,6 +2223,21 @@ public class TestProgramsFast extends TestPrograms {
       compileAndCompare("struct-directives.c");
    }
 
+   @Test
+   public void testUnion6() throws IOException {
+      compileAndCompare("union-6.c");
+   }
+
+   @Test
+   public void testUnion5() throws IOException {
+      compileAndCompare("union-5.c");
+   }
+
+   @Test
+   public void testUnion4() throws IOException {
+      compileAndCompare("union-4.c");
+   }
+
    @Test
    public void testUnion3() throws IOException {
       compileAndCompare("union-3.c");
diff --git a/src/test/kc/union-4.c b/src/test/kc/union-4.c
new file mode 100644
index 000000000..a923a7217
--- /dev/null
+++ b/src/test/kc/union-4.c
@@ -0,0 +1,21 @@
+// Minimal union with C-Standard behavior - union with array member
+
+typedef unsigned long uint32_t;
+typedef unsigned char byte_t;
+
+typedef union IPV4 {
+   uint32_t d;
+   byte_t b[4];
+} IPV4;
+
+IPV4 ipv4;
+
+char* const SCREEN = (char*)0x0400;
+
+void main() {
+    ipv4.d = 0x12345678ul;
+    SCREEN[0] = ipv4.b[3];
+    SCREEN[1] = ipv4.b[2];
+    SCREEN[2] = ipv4.b[1];
+    SCREEN[3] = ipv4.b[0]; 
+}
\ No newline at end of file
diff --git a/src/test/kc/union-5.c b/src/test/kc/union-5.c
new file mode 100644
index 000000000..9f4c7413a
--- /dev/null
+++ b/src/test/kc/union-5.c
@@ -0,0 +1,20 @@
+// Minimal union with C-Standard behavior - union initializer
+
+typedef unsigned long uint32_t;
+typedef unsigned char byte_t;
+
+typedef union IPV4 {
+   uint32_t d;
+   byte_t b[4];
+} IPV4;
+
+IPV4 ipv4 = { 0x12345678ul };
+
+char* const SCREEN = (char*)0x0400;
+
+void main() {
+    SCREEN[0] = ipv4.b[3];
+    SCREEN[1] = ipv4.b[2];
+    SCREEN[2] = ipv4.b[1];
+    SCREEN[3] = ipv4.b[0];
+}
\ No newline at end of file
diff --git a/src/test/kc/union-6.c b/src/test/kc/union-6.c
new file mode 100644
index 000000000..9bfcdf446
--- /dev/null
+++ b/src/test/kc/union-6.c
@@ -0,0 +1,16 @@
+// Minimal union with C-Standard behavior - union initializer with first element smaller than second
+
+typedef union Data {
+   unsigned char b;
+   unsigned int w;
+} Data;
+
+Data data  = { 12 };
+
+char* const SCREEN = (char*)0x0400;
+
+void main() {
+    data.w = 0x1234;
+    SCREEN[0] = BYTE1(data.w);
+    SCREEN[1] = BYTE0(data.w);
+}
\ No newline at end of file
diff --git a/src/test/ref/union-4.asm b/src/test/ref/union-4.asm
new file mode 100644
index 000000000..999f33683
--- /dev/null
+++ b/src/test/ref/union-4.asm
@@ -0,0 +1,38 @@
+// Minimal union with C-Standard behavior - union with array member
+  // Commodore 64 PRG executable file
+.file [name="union-4.prg", type="prg", segments="Program"]
+.segmentdef Program [segments="Basic, Code, Data"]
+.segmentdef Basic [start=$0801]
+.segmentdef Code [start=$80d]
+.segmentdef Data [startAfter="Code"]
+.segment Basic
+:BasicUpstart(main)
+  .const SIZEOF_UNION_IPV4 = 4
+  .label SCREEN = $400
+.segment Code
+main: {
+    // ipv4.d = 0x12345678ul
+    lda #<$12345678
+    sta ipv4
+    lda #>$12345678
+    sta ipv4+1
+    lda #<$12345678>>$10
+    sta ipv4+2
+    lda #>$12345678>>$10
+    sta ipv4+3
+    // SCREEN[0] = ipv4.b[3]
+    sta SCREEN
+    // SCREEN[1] = ipv4.b[2]
+    lda ipv4+2
+    sta SCREEN+1
+    // SCREEN[2] = ipv4.b[1]
+    lda ipv4+1
+    sta SCREEN+2
+    // SCREEN[3] = ipv4.b[0]
+    lda ipv4
+    sta SCREEN+3
+    // }
+    rts
+}
+.segment Data
+  ipv4: .fill SIZEOF_UNION_IPV4, 0
diff --git a/src/test/ref/union-4.cfg b/src/test/ref/union-4.cfg
new file mode 100644
index 000000000..e48326cbd
--- /dev/null
+++ b/src/test/ref/union-4.cfg
@@ -0,0 +1,12 @@
+
+void main()
+main: scope:[main]  from
+  [0] *((dword*)&ipv4) = $12345678
+  [1] *SCREEN = *((byte*)&ipv4+3)
+  [2] *(SCREEN+1) = *((byte*)&ipv4+2)
+  [3] *(SCREEN+2) = *((byte*)&ipv4+1)
+  [4] *(SCREEN+3) = *((byte*)&ipv4)
+  to:main::@return
+main::@return: scope:[main]  from main
+  [5] return 
+  to:@return
diff --git a/src/test/ref/union-4.log b/src/test/ref/union-4.log
new file mode 100644
index 000000000..7a7cc7eec
--- /dev/null
+++ b/src/test/ref/union-4.log
@@ -0,0 +1,257 @@
+Fixing struct type size union IPV4 to 4
+Fixing struct type size union IPV4 to 4
+Fixing struct type SIZE_OF union IPV4 to 4
+Fixing struct type SIZE_OF union IPV4 to 4
+
+CONTROL FLOW GRAPH SSA
+
+void main()
+main: scope:[main]  from __start
+  *((dword*)&ipv4+OFFSET_UNION_IPV4_D) = $12345678
+  SCREEN[0] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[3]
+  SCREEN[1] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[2]
+  SCREEN[2] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[1]
+  SCREEN[3] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[0]
+  to:main::@return
+main::@return: scope:[main]  from main
+  return 
+  to:@return
+
+void __start()
+__start: scope:[__start]  from
+  call main 
+  to:__start::@1
+__start::@1: scope:[__start]  from __start
+  to:__start::@return
+__start::@return: scope:[__start]  from __start::@1
+  return 
+  to:@return
+
+SYMBOL TABLE SSA
+constant byte OFFSET_UNION_IPV4_B = 0
+constant byte OFFSET_UNION_IPV4_D = 0
+constant byte* const SCREEN = (byte*)$400
+void __start()
+union IPV4 ipv4 loadstore = {}
+void main()
+
+Adding number conversion cast (unumber) 3 in SCREEN[0] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[3]
+Adding number conversion cast (unumber) 0 in SCREEN[0] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[(unumber)3]
+Adding number conversion cast (unumber) 2 in SCREEN[1] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[2]
+Adding number conversion cast (unumber) 1 in SCREEN[1] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[(unumber)2]
+Adding number conversion cast (unumber) 1 in SCREEN[2] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[1]
+Adding number conversion cast (unumber) 2 in SCREEN[2] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[(unumber)1]
+Adding number conversion cast (unumber) 0 in SCREEN[3] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[0]
+Adding number conversion cast (unumber) 3 in SCREEN[3] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[(unumber)0]
+Successful SSA optimization PassNAddNumberTypeConversions
+Simplifying constant pointer cast (byte*) 1024
+Simplifying constant integer cast 3
+Simplifying constant integer cast 0
+Simplifying constant integer cast 2
+Simplifying constant integer cast 1
+Simplifying constant integer cast 1
+Simplifying constant integer cast 2
+Simplifying constant integer cast 0
+Simplifying constant integer cast 3
+Successful SSA optimization PassNCastSimplification
+Finalized unsigned number type (byte) 3
+Finalized unsigned number type (byte) 0
+Finalized unsigned number type (byte) 2
+Finalized unsigned number type (byte) 1
+Finalized unsigned number type (byte) 1
+Finalized unsigned number type (byte) 2
+Finalized unsigned number type (byte) 0
+Finalized unsigned number type (byte) 3
+Successful SSA optimization PassNFinalizeNumberTypeConversions
+Simplifying expression containing zero (dword*)&ipv4 in [0] *((dword*)&ipv4+OFFSET_UNION_IPV4_D) = $12345678
+Simplifying expression containing zero (byte*)&ipv4 in [1] SCREEN[0] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[3]
+Simplifying expression containing zero SCREEN in [1] SCREEN[0] = ((byte*)&ipv4)[3]
+Simplifying expression containing zero (byte*)&ipv4 in [2] SCREEN[1] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[2]
+Simplifying expression containing zero (byte*)&ipv4 in [3] SCREEN[2] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[1]
+Simplifying expression containing zero (byte*)&ipv4+OFFSET_UNION_IPV4_B in [4] SCREEN[3] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[0]
+Simplifying expression containing zero (byte*)&ipv4 in [4] SCREEN[3] = *((byte*)&ipv4+OFFSET_UNION_IPV4_B)
+Successful SSA optimization PassNSimplifyExpressionWithZero
+Eliminating unused constant OFFSET_UNION_IPV4_D
+Eliminating unused constant OFFSET_UNION_IPV4_B
+Successful SSA optimization PassNEliminateUnusedVars
+Removing unused procedure __start
+Removing unused procedure block __start
+Removing unused procedure block __start::@1
+Removing unused procedure block __start::@return
+Successful SSA optimization PassNEliminateEmptyStart
+Consolidated array index constant in *((byte*)&ipv4+3)
+Consolidated array index constant in *((byte*)&ipv4+2)
+Consolidated array index constant in *(SCREEN+1)
+Consolidated array index constant in *((byte*)&ipv4+1)
+Consolidated array index constant in *(SCREEN+2)
+Consolidated array index constant in *(SCREEN+3)
+Successful SSA optimization Pass2ConstantAdditionElimination
+Finalized unsigned number type (byte) 4
+Finalized unsigned number type (byte) 4
+Successful SSA optimization PassNFinalizeNumberTypeConversions
+CALL GRAPH
+
+Created 0 initial phi equivalence classes
+Coalesced down to 0 phi equivalence classes
+
+FINAL CONTROL FLOW GRAPH
+
+void main()
+main: scope:[main]  from
+  [0] *((dword*)&ipv4) = $12345678
+  [1] *SCREEN = *((byte*)&ipv4+3)
+  [2] *(SCREEN+1) = *((byte*)&ipv4+2)
+  [3] *(SCREEN+2) = *((byte*)&ipv4+1)
+  [4] *(SCREEN+3) = *((byte*)&ipv4)
+  to:main::@return
+main::@return: scope:[main]  from main
+  [5] return 
+  to:@return
+
+
+VARIABLE REGISTER WEIGHTS
+union IPV4 ipv4 loadstore = {}
+void main()
+
+Initial phi equivalence classes
+Added variable ipv4 to live range equivalence class [ ipv4 ]
+Complete equivalence classes
+[ ipv4 ]
+Allocated mem[4] [ ipv4 ]
+REGISTER UPLIFT POTENTIAL REGISTERS
+Statement [0] *((dword*)&ipv4) = $12345678 [ ipv4 ] (  [ ipv4 ] { }  ) always clobbers reg byte a 
+Statement [1] *SCREEN = *((byte*)&ipv4+3) [ ipv4 ] (  [ ipv4 ] { }  ) always clobbers reg byte a 
+Statement [2] *(SCREEN+1) = *((byte*)&ipv4+2) [ ipv4 ] (  [ ipv4 ] { }  ) always clobbers reg byte a 
+Statement [3] *(SCREEN+2) = *((byte*)&ipv4+1) [ ipv4 ] (  [ ipv4 ] { }  ) always clobbers reg byte a 
+Statement [4] *(SCREEN+3) = *((byte*)&ipv4) [ ] (  [ ] { }  ) always clobbers reg byte a 
+Potential registers mem[4] [ ipv4 ] : mem[4] , 
+
+REGISTER UPLIFT SCOPES
+Uplift Scope [IPV4] 
+Uplift Scope [main] 
+Uplift Scope [] 0: mem[4] [ ipv4 ] 
+
+Uplifting [IPV4] best 65 combination 
+Uplifting [main] best 65 combination 
+Uplifting [] best 65 combination mem[4] [ ipv4 ] 
+
+ASSEMBLER BEFORE OPTIMIZATION
+  // File Comments
+// Minimal union with C-Standard behavior - union with array member
+  // Upstart
+  // Commodore 64 PRG executable file
+.file [name="union-4.prg", type="prg", segments="Program"]
+.segmentdef Program [segments="Basic, Code, Data"]
+.segmentdef Basic [start=$0801]
+.segmentdef Code [start=$80d]
+.segmentdef Data [startAfter="Code"]
+.segment Basic
+:BasicUpstart(main)
+  // Global Constants & labels
+  .const SIZEOF_UNION_IPV4 = 4
+  .label SCREEN = $400
+.segment Code
+  // main
+main: {
+    // [0] *((dword*)&ipv4) = $12345678 -- _deref_pduc1=vduc2 
+    lda #<$12345678
+    sta ipv4
+    lda #>$12345678
+    sta ipv4+1
+    lda #<$12345678>>$10
+    sta ipv4+2
+    lda #>$12345678>>$10
+    sta ipv4+3
+    // [1] *SCREEN = *((byte*)&ipv4+3) -- _deref_pbuc1=_deref_pbuc2 
+    lda ipv4+3
+    sta SCREEN
+    // [2] *(SCREEN+1) = *((byte*)&ipv4+2) -- _deref_pbuc1=_deref_pbuc2 
+    lda ipv4+2
+    sta SCREEN+1
+    // [3] *(SCREEN+2) = *((byte*)&ipv4+1) -- _deref_pbuc1=_deref_pbuc2 
+    lda ipv4+1
+    sta SCREEN+2
+    // [4] *(SCREEN+3) = *((byte*)&ipv4) -- _deref_pbuc1=_deref_pbuc2 
+    lda ipv4
+    sta SCREEN+3
+    jmp __breturn
+    // main::@return
+  __breturn:
+    // [5] return 
+    rts
+}
+  // File Data
+.segment Data
+  ipv4: .fill SIZEOF_UNION_IPV4, 0
+
+ASSEMBLER OPTIMIZATIONS
+Removing instruction jmp __breturn
+Succesful ASM optimization Pass5NextJumpElimination
+Removing instruction lda ipv4+3
+Succesful ASM optimization Pass5UnnecesaryLoadElimination
+Removing instruction __breturn:
+Succesful ASM optimization Pass5UnusedLabelElimination
+
+FINAL SYMBOL TABLE
+constant byte* const SCREEN = (byte*) 1024
+constant byte SIZEOF_UNION_IPV4 = 4
+union IPV4 ipv4 loadstore mem[4] = {}
+void main()
+
+mem[4] [ ipv4 ]
+
+
+FINAL ASSEMBLER
+Score: 58
+
+  // File Comments
+// Minimal union with C-Standard behavior - union with array member
+  // Upstart
+  // Commodore 64 PRG executable file
+.file [name="union-4.prg", type="prg", segments="Program"]
+.segmentdef Program [segments="Basic, Code, Data"]
+.segmentdef Basic [start=$0801]
+.segmentdef Code [start=$80d]
+.segmentdef Data [startAfter="Code"]
+.segment Basic
+:BasicUpstart(main)
+  // Global Constants & labels
+  .const SIZEOF_UNION_IPV4 = 4
+  .label SCREEN = $400
+.segment Code
+  // main
+main: {
+    // ipv4.d = 0x12345678ul
+    // [0] *((dword*)&ipv4) = $12345678 -- _deref_pduc1=vduc2 
+    lda #<$12345678
+    sta ipv4
+    lda #>$12345678
+    sta ipv4+1
+    lda #<$12345678>>$10
+    sta ipv4+2
+    lda #>$12345678>>$10
+    sta ipv4+3
+    // SCREEN[0] = ipv4.b[3]
+    // [1] *SCREEN = *((byte*)&ipv4+3) -- _deref_pbuc1=_deref_pbuc2 
+    sta SCREEN
+    // SCREEN[1] = ipv4.b[2]
+    // [2] *(SCREEN+1) = *((byte*)&ipv4+2) -- _deref_pbuc1=_deref_pbuc2 
+    lda ipv4+2
+    sta SCREEN+1
+    // SCREEN[2] = ipv4.b[1]
+    // [3] *(SCREEN+2) = *((byte*)&ipv4+1) -- _deref_pbuc1=_deref_pbuc2 
+    lda ipv4+1
+    sta SCREEN+2
+    // SCREEN[3] = ipv4.b[0]
+    // [4] *(SCREEN+3) = *((byte*)&ipv4) -- _deref_pbuc1=_deref_pbuc2 
+    lda ipv4
+    sta SCREEN+3
+    // main::@return
+    // }
+    // [5] return 
+    rts
+}
+  // File Data
+.segment Data
+  ipv4: .fill SIZEOF_UNION_IPV4, 0
+
diff --git a/src/test/ref/union-4.sym b/src/test/ref/union-4.sym
new file mode 100644
index 000000000..10cfef106
--- /dev/null
+++ b/src/test/ref/union-4.sym
@@ -0,0 +1,6 @@
+constant byte* const SCREEN = (byte*) 1024
+constant byte SIZEOF_UNION_IPV4 = 4
+union IPV4 ipv4 loadstore mem[4] = {}
+void main()
+
+mem[4] [ ipv4 ]
diff --git a/src/test/ref/union-5.asm b/src/test/ref/union-5.asm
new file mode 100644
index 000000000..35f2ff2a0
--- /dev/null
+++ b/src/test/ref/union-5.asm
@@ -0,0 +1,29 @@
+// Minimal union with C-Standard behavior - union initializer
+  // Commodore 64 PRG executable file
+.file [name="union-5.prg", type="prg", segments="Program"]
+.segmentdef Program [segments="Basic, Code, Data"]
+.segmentdef Basic [start=$0801]
+.segmentdef Code [start=$80d]
+.segmentdef Data [startAfter="Code"]
+.segment Basic
+:BasicUpstart(main)
+  .label SCREEN = $400
+.segment Code
+main: {
+    // SCREEN[0] = ipv4.b[3]
+    lda ipv4+3
+    sta SCREEN
+    // SCREEN[1] = ipv4.b[2]
+    lda ipv4+2
+    sta SCREEN+1
+    // SCREEN[2] = ipv4.b[1]
+    lda ipv4+1
+    sta SCREEN+2
+    // SCREEN[3] = ipv4.b[0]
+    lda ipv4
+    sta SCREEN+3
+    // }
+    rts
+}
+.segment Data
+  ipv4: .dword $12345678
diff --git a/src/test/ref/union-5.cfg b/src/test/ref/union-5.cfg
new file mode 100644
index 000000000..f4a844848
--- /dev/null
+++ b/src/test/ref/union-5.cfg
@@ -0,0 +1,11 @@
+
+void main()
+main: scope:[main]  from
+  [0] *SCREEN = *((byte*)&ipv4+3)
+  [1] *(SCREEN+1) = *((byte*)&ipv4+2)
+  [2] *(SCREEN+2) = *((byte*)&ipv4+1)
+  [3] *(SCREEN+3) = *((byte*)&ipv4)
+  to:main::@return
+main::@return: scope:[main]  from main
+  [4] return 
+  to:@return
diff --git a/src/test/ref/union-5.log b/src/test/ref/union-5.log
new file mode 100644
index 000000000..55ee93083
--- /dev/null
+++ b/src/test/ref/union-5.log
@@ -0,0 +1,228 @@
+Fixing struct type size union IPV4 to 4
+Fixing struct type size union IPV4 to 4
+Fixing struct type SIZE_OF union IPV4 to 4
+Fixing struct type SIZE_OF union IPV4 to 4
+
+CONTROL FLOW GRAPH SSA
+
+void main()
+main: scope:[main]  from __start
+  SCREEN[0] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[3]
+  SCREEN[1] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[2]
+  SCREEN[2] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[1]
+  SCREEN[3] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[0]
+  to:main::@return
+main::@return: scope:[main]  from main
+  return 
+  to:@return
+
+void __start()
+__start: scope:[__start]  from
+  call main 
+  to:__start::@1
+__start::@1: scope:[__start]  from __start
+  to:__start::@return
+__start::@return: scope:[__start]  from __start::@1
+  return 
+  to:@return
+
+SYMBOL TABLE SSA
+constant byte OFFSET_UNION_IPV4_B = 0
+constant byte* const SCREEN = (byte*)$400
+void __start()
+union IPV4 ipv4 loadstore = { d: $12345678 }
+void main()
+
+Adding number conversion cast (unumber) 3 in SCREEN[0] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[3]
+Adding number conversion cast (unumber) 0 in SCREEN[0] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[(unumber)3]
+Adding number conversion cast (unumber) 2 in SCREEN[1] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[2]
+Adding number conversion cast (unumber) 1 in SCREEN[1] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[(unumber)2]
+Adding number conversion cast (unumber) 1 in SCREEN[2] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[1]
+Adding number conversion cast (unumber) 2 in SCREEN[2] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[(unumber)1]
+Adding number conversion cast (unumber) 0 in SCREEN[3] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[0]
+Adding number conversion cast (unumber) 3 in SCREEN[3] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[(unumber)0]
+Successful SSA optimization PassNAddNumberTypeConversions
+Simplifying constant pointer cast (byte*) 1024
+Simplifying constant integer cast 3
+Simplifying constant integer cast 0
+Simplifying constant integer cast 2
+Simplifying constant integer cast 1
+Simplifying constant integer cast 1
+Simplifying constant integer cast 2
+Simplifying constant integer cast 0
+Simplifying constant integer cast 3
+Successful SSA optimization PassNCastSimplification
+Finalized unsigned number type (byte) 3
+Finalized unsigned number type (byte) 0
+Finalized unsigned number type (byte) 2
+Finalized unsigned number type (byte) 1
+Finalized unsigned number type (byte) 1
+Finalized unsigned number type (byte) 2
+Finalized unsigned number type (byte) 0
+Finalized unsigned number type (byte) 3
+Successful SSA optimization PassNFinalizeNumberTypeConversions
+Simplifying expression containing zero (byte*)&ipv4 in [0] SCREEN[0] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[3]
+Simplifying expression containing zero SCREEN in [0] SCREEN[0] = ((byte*)&ipv4)[3]
+Simplifying expression containing zero (byte*)&ipv4 in [1] SCREEN[1] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[2]
+Simplifying expression containing zero (byte*)&ipv4 in [2] SCREEN[2] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[1]
+Simplifying expression containing zero (byte*)&ipv4+OFFSET_UNION_IPV4_B in [3] SCREEN[3] = ((byte*)&ipv4+OFFSET_UNION_IPV4_B)[0]
+Simplifying expression containing zero (byte*)&ipv4 in [3] SCREEN[3] = *((byte*)&ipv4+OFFSET_UNION_IPV4_B)
+Successful SSA optimization PassNSimplifyExpressionWithZero
+Eliminating unused constant OFFSET_UNION_IPV4_B
+Successful SSA optimization PassNEliminateUnusedVars
+Removing unused procedure __start
+Removing unused procedure block __start
+Removing unused procedure block __start::@1
+Removing unused procedure block __start::@return
+Successful SSA optimization PassNEliminateEmptyStart
+Consolidated array index constant in *((byte*)&ipv4+3)
+Consolidated array index constant in *((byte*)&ipv4+2)
+Consolidated array index constant in *(SCREEN+1)
+Consolidated array index constant in *((byte*)&ipv4+1)
+Consolidated array index constant in *(SCREEN+2)
+Consolidated array index constant in *(SCREEN+3)
+Successful SSA optimization Pass2ConstantAdditionElimination
+Finalized unsigned number type (byte) 4
+Finalized unsigned number type (byte) 4
+Successful SSA optimization PassNFinalizeNumberTypeConversions
+CALL GRAPH
+
+Created 0 initial phi equivalence classes
+Coalesced down to 0 phi equivalence classes
+
+FINAL CONTROL FLOW GRAPH
+
+void main()
+main: scope:[main]  from
+  [0] *SCREEN = *((byte*)&ipv4+3)
+  [1] *(SCREEN+1) = *((byte*)&ipv4+2)
+  [2] *(SCREEN+2) = *((byte*)&ipv4+1)
+  [3] *(SCREEN+3) = *((byte*)&ipv4)
+  to:main::@return
+main::@return: scope:[main]  from main
+  [4] return 
+  to:@return
+
+
+VARIABLE REGISTER WEIGHTS
+union IPV4 ipv4 loadstore = { d: $12345678 }
+void main()
+
+Initial phi equivalence classes
+Added variable ipv4 to live range equivalence class [ ipv4 ]
+Complete equivalence classes
+[ ipv4 ]
+Allocated mem[4] [ ipv4 ]
+REGISTER UPLIFT POTENTIAL REGISTERS
+Statement [0] *SCREEN = *((byte*)&ipv4+3) [ ipv4 ] (  [ ipv4 ] { }  ) always clobbers reg byte a 
+Statement [1] *(SCREEN+1) = *((byte*)&ipv4+2) [ ipv4 ] (  [ ipv4 ] { }  ) always clobbers reg byte a 
+Statement [2] *(SCREEN+2) = *((byte*)&ipv4+1) [ ipv4 ] (  [ ipv4 ] { }  ) always clobbers reg byte a 
+Statement [3] *(SCREEN+3) = *((byte*)&ipv4) [ ] (  [ ] { }  ) always clobbers reg byte a 
+Potential registers mem[4] [ ipv4 ] : mem[4] , 
+
+REGISTER UPLIFT SCOPES
+Uplift Scope [IPV4] 
+Uplift Scope [main] 
+Uplift Scope [] 0: mem[4] [ ipv4 ] 
+
+Uplifting [IPV4] best 41 combination 
+Uplifting [main] best 41 combination 
+Uplifting [] best 41 combination mem[4] [ ipv4 ] 
+
+ASSEMBLER BEFORE OPTIMIZATION
+  // File Comments
+// Minimal union with C-Standard behavior - union initializer
+  // Upstart
+  // Commodore 64 PRG executable file
+.file [name="union-5.prg", type="prg", segments="Program"]
+.segmentdef Program [segments="Basic, Code, Data"]
+.segmentdef Basic [start=$0801]
+.segmentdef Code [start=$80d]
+.segmentdef Data [startAfter="Code"]
+.segment Basic
+:BasicUpstart(main)
+  // Global Constants & labels
+  .label SCREEN = $400
+.segment Code
+  // main
+main: {
+    // [0] *SCREEN = *((byte*)&ipv4+3) -- _deref_pbuc1=_deref_pbuc2 
+    lda ipv4+3
+    sta SCREEN
+    // [1] *(SCREEN+1) = *((byte*)&ipv4+2) -- _deref_pbuc1=_deref_pbuc2 
+    lda ipv4+2
+    sta SCREEN+1
+    // [2] *(SCREEN+2) = *((byte*)&ipv4+1) -- _deref_pbuc1=_deref_pbuc2 
+    lda ipv4+1
+    sta SCREEN+2
+    // [3] *(SCREEN+3) = *((byte*)&ipv4) -- _deref_pbuc1=_deref_pbuc2 
+    lda ipv4
+    sta SCREEN+3
+    jmp __breturn
+    // main::@return
+  __breturn:
+    // [4] return 
+    rts
+}
+  // File Data
+.segment Data
+  ipv4: .dword $12345678
+
+ASSEMBLER OPTIMIZATIONS
+Removing instruction jmp __breturn
+Succesful ASM optimization Pass5NextJumpElimination
+Removing instruction __breturn:
+Succesful ASM optimization Pass5UnusedLabelElimination
+
+FINAL SYMBOL TABLE
+constant byte* const SCREEN = (byte*) 1024
+union IPV4 ipv4 loadstore mem[4] = { d: $12345678 }
+void main()
+
+mem[4] [ ipv4 ]
+
+
+FINAL ASSEMBLER
+Score: 38
+
+  // File Comments
+// Minimal union with C-Standard behavior - union initializer
+  // Upstart
+  // Commodore 64 PRG executable file
+.file [name="union-5.prg", type="prg", segments="Program"]
+.segmentdef Program [segments="Basic, Code, Data"]
+.segmentdef Basic [start=$0801]
+.segmentdef Code [start=$80d]
+.segmentdef Data [startAfter="Code"]
+.segment Basic
+:BasicUpstart(main)
+  // Global Constants & labels
+  .label SCREEN = $400
+.segment Code
+  // main
+main: {
+    // SCREEN[0] = ipv4.b[3]
+    // [0] *SCREEN = *((byte*)&ipv4+3) -- _deref_pbuc1=_deref_pbuc2 
+    lda ipv4+3
+    sta SCREEN
+    // SCREEN[1] = ipv4.b[2]
+    // [1] *(SCREEN+1) = *((byte*)&ipv4+2) -- _deref_pbuc1=_deref_pbuc2 
+    lda ipv4+2
+    sta SCREEN+1
+    // SCREEN[2] = ipv4.b[1]
+    // [2] *(SCREEN+2) = *((byte*)&ipv4+1) -- _deref_pbuc1=_deref_pbuc2 
+    lda ipv4+1
+    sta SCREEN+2
+    // SCREEN[3] = ipv4.b[0]
+    // [3] *(SCREEN+3) = *((byte*)&ipv4) -- _deref_pbuc1=_deref_pbuc2 
+    lda ipv4
+    sta SCREEN+3
+    // main::@return
+    // }
+    // [4] return 
+    rts
+}
+  // File Data
+.segment Data
+  ipv4: .dword $12345678
+
diff --git a/src/test/ref/union-5.sym b/src/test/ref/union-5.sym
new file mode 100644
index 000000000..31ea575d1
--- /dev/null
+++ b/src/test/ref/union-5.sym
@@ -0,0 +1,5 @@
+constant byte* const SCREEN = (byte*) 1024
+union IPV4 ipv4 loadstore mem[4] = { d: $12345678 }
+void main()
+
+mem[4] [ ipv4 ]
diff --git a/src/test/ref/union-6.asm b/src/test/ref/union-6.asm
new file mode 100644
index 000000000..ed3ba2f23
--- /dev/null
+++ b/src/test/ref/union-6.asm
@@ -0,0 +1,30 @@
+// Minimal union with C-Standard behavior - union initializer with first element smaller than second
+  // Commodore 64 PRG executable file
+.file [name="union-6.prg", type="prg", segments="Program"]
+.segmentdef Program [segments="Basic, Code, Data"]
+.segmentdef Basic [start=$0801]
+.segmentdef Code [start=$80d]
+.segmentdef Data [startAfter="Code"]
+.segment Basic
+:BasicUpstart(main)
+  .label SCREEN = $400
+.segment Code
+main: {
+    // data.w = 0x1234
+    lda #<$1234
+    sta data
+    lda #>$1234
+    sta data+1
+    // BYTE1(data.w)
+    // SCREEN[0] = BYTE1(data.w)
+    sta SCREEN
+    // BYTE0(data.w)
+    lda data
+    // SCREEN[1] = BYTE0(data.w)
+    sta SCREEN+1
+    // }
+    rts
+}
+.segment Data
+  data: .byte $c
+  .fill 1, 0
diff --git a/src/test/ref/union-6.cfg b/src/test/ref/union-6.cfg
new file mode 100644
index 000000000..c701abb6a
--- /dev/null
+++ b/src/test/ref/union-6.cfg
@@ -0,0 +1,12 @@
+
+void main()
+main: scope:[main]  from
+  [0] *((word*)&data) = $1234
+  [1] main::$0 = byte1  *((word*)&data)
+  [2] *SCREEN = main::$0
+  [3] main::$1 = byte0  *((word*)&data)
+  [4] *(SCREEN+1) = main::$1
+  to:main::@return
+main::@return: scope:[main]  from main
+  [5] return 
+  to:@return
diff --git a/src/test/ref/union-6.log b/src/test/ref/union-6.log
new file mode 100644
index 000000000..6ccd284bf
--- /dev/null
+++ b/src/test/ref/union-6.log
@@ -0,0 +1,222 @@
+
+CONTROL FLOW GRAPH SSA
+
+void main()
+main: scope:[main]  from __start
+  *((word*)&data+OFFSET_UNION_DATA_W) = $1234
+  main::$0 = byte1  *((word*)&data+OFFSET_UNION_DATA_W)
+  SCREEN[0] = main::$0
+  main::$1 = byte0  *((word*)&data+OFFSET_UNION_DATA_W)
+  SCREEN[1] = main::$1
+  to:main::@return
+main::@return: scope:[main]  from main
+  return 
+  to:@return
+
+void __start()
+__start: scope:[__start]  from
+  call main 
+  to:__start::@1
+__start::@1: scope:[__start]  from __start
+  to:__start::@return
+__start::@return: scope:[__start]  from __start::@1
+  return 
+  to:@return
+
+SYMBOL TABLE SSA
+constant byte OFFSET_UNION_DATA_W = 0
+constant byte* const SCREEN = (byte*)$400
+void __start()
+union Data data loadstore = { b: $c }
+void main()
+byte~ main::$0
+byte~ main::$1
+
+Adding number conversion cast (unumber) $1234 in *((word*)&data+OFFSET_UNION_DATA_W) = $1234
+Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$0
+Adding number conversion cast (unumber) 1 in SCREEN[1] = main::$1
+Successful SSA optimization PassNAddNumberTypeConversions
+Inlining cast *((word*)&data+OFFSET_UNION_DATA_W) = (unumber)$1234
+Successful SSA optimization Pass2InlineCast
+Simplifying constant pointer cast (byte*) 1024
+Simplifying constant integer cast $1234
+Simplifying constant integer cast 0
+Simplifying constant integer cast 1
+Successful SSA optimization PassNCastSimplification
+Finalized unsigned number type (word) $1234
+Finalized unsigned number type (byte) 0
+Finalized unsigned number type (byte) 1
+Successful SSA optimization PassNFinalizeNumberTypeConversions
+Simplifying expression containing zero (word*)&data in [0] *((word*)&data+OFFSET_UNION_DATA_W) = $1234
+Simplifying expression containing zero (word*)&data in [1] main::$0 = byte1  *((word*)&data+OFFSET_UNION_DATA_W)
+Simplifying expression containing zero SCREEN in [2] SCREEN[0] = main::$0
+Simplifying expression containing zero (word*)&data in [3] main::$1 = byte0  *((word*)&data+OFFSET_UNION_DATA_W)
+Successful SSA optimization PassNSimplifyExpressionWithZero
+Eliminating unused constant OFFSET_UNION_DATA_W
+Successful SSA optimization PassNEliminateUnusedVars
+Removing unused procedure __start
+Removing unused procedure block __start
+Removing unused procedure block __start::@1
+Removing unused procedure block __start::@return
+Successful SSA optimization PassNEliminateEmptyStart
+Consolidated array index constant in *(SCREEN+1)
+Successful SSA optimization Pass2ConstantAdditionElimination
+CALL GRAPH
+
+Created 0 initial phi equivalence classes
+Coalesced down to 0 phi equivalence classes
+
+FINAL CONTROL FLOW GRAPH
+
+void main()
+main: scope:[main]  from
+  [0] *((word*)&data) = $1234
+  [1] main::$0 = byte1  *((word*)&data)
+  [2] *SCREEN = main::$0
+  [3] main::$1 = byte0  *((word*)&data)
+  [4] *(SCREEN+1) = main::$1
+  to:main::@return
+main::@return: scope:[main]  from main
+  [5] return 
+  to:@return
+
+
+VARIABLE REGISTER WEIGHTS
+union Data data loadstore = { b: $c }
+void main()
+byte~ main::$0 4.0
+byte~ main::$1 4.0
+
+Initial phi equivalence classes
+Added variable main::$0 to live range equivalence class [ main::$0 ]
+Added variable main::$1 to live range equivalence class [ main::$1 ]
+Added variable data to live range equivalence class [ data ]
+Complete equivalence classes
+[ main::$0 ]
+[ main::$1 ]
+[ data ]
+Allocated zp[1]:2 [ main::$0 ]
+Allocated zp[1]:3 [ main::$1 ]
+Allocated mem[2] [ data ]
+REGISTER UPLIFT POTENTIAL REGISTERS
+Statement [0] *((word*)&data) = $1234 [ data ] (  [ data ] { }  ) always clobbers reg byte a 
+Potential registers zp[1]:2 [ main::$0 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y , 
+Potential registers zp[1]:3 [ main::$1 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y , 
+Potential registers mem[2] [ data ] : mem[2] , 
+
+REGISTER UPLIFT SCOPES
+Uplift Scope [main] 4: zp[1]:2 [ main::$0 ] 4: zp[1]:3 [ main::$1 ] 
+Uplift Scope [Data] 
+Uplift Scope [] 0: mem[2] [ data ] 
+
+Uplifting [main] best 37 combination reg byte a [ main::$0 ] reg byte a [ main::$1 ] 
+Uplifting [Data] best 37 combination 
+Uplifting [] best 37 combination mem[2] [ data ] 
+
+ASSEMBLER BEFORE OPTIMIZATION
+  // File Comments
+// Minimal union with C-Standard behavior - union initializer with first element smaller than second
+  // Upstart
+  // Commodore 64 PRG executable file
+.file [name="union-6.prg", type="prg", segments="Program"]
+.segmentdef Program [segments="Basic, Code, Data"]
+.segmentdef Basic [start=$0801]
+.segmentdef Code [start=$80d]
+.segmentdef Data [startAfter="Code"]
+.segment Basic
+:BasicUpstart(main)
+  // Global Constants & labels
+  .label SCREEN = $400
+.segment Code
+  // main
+main: {
+    // [0] *((word*)&data) = $1234 -- _deref_pwuc1=vwuc2 
+    lda #<$1234
+    sta data
+    lda #>$1234
+    sta data+1
+    // [1] main::$0 = byte1  *((word*)&data) -- vbuaa=_byte1__deref_pwuc1 
+    lda data+1
+    // [2] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa 
+    sta SCREEN
+    // [3] main::$1 = byte0  *((word*)&data) -- vbuaa=_byte0__deref_pwuc1 
+    lda data
+    // [4] *(SCREEN+1) = main::$1 -- _deref_pbuc1=vbuaa 
+    sta SCREEN+1
+    jmp __breturn
+    // main::@return
+  __breturn:
+    // [5] return 
+    rts
+}
+  // File Data
+.segment Data
+  data: .byte $c
+  .fill 1, 0
+
+ASSEMBLER OPTIMIZATIONS
+Removing instruction jmp __breturn
+Succesful ASM optimization Pass5NextJumpElimination
+Removing instruction lda data+1
+Succesful ASM optimization Pass5UnnecesaryLoadElimination
+Removing instruction __breturn:
+Succesful ASM optimization Pass5UnusedLabelElimination
+
+FINAL SYMBOL TABLE
+constant byte* const SCREEN = (byte*) 1024
+union Data data loadstore mem[2] = { b: $c }
+void main()
+byte~ main::$0 reg byte a 4.0
+byte~ main::$1 reg byte a 4.0
+
+reg byte a [ main::$0 ]
+reg byte a [ main::$1 ]
+mem[2] [ data ]
+
+
+FINAL ASSEMBLER
+Score: 30
+
+  // File Comments
+// Minimal union with C-Standard behavior - union initializer with first element smaller than second
+  // Upstart
+  // Commodore 64 PRG executable file
+.file [name="union-6.prg", type="prg", segments="Program"]
+.segmentdef Program [segments="Basic, Code, Data"]
+.segmentdef Basic [start=$0801]
+.segmentdef Code [start=$80d]
+.segmentdef Data [startAfter="Code"]
+.segment Basic
+:BasicUpstart(main)
+  // Global Constants & labels
+  .label SCREEN = $400
+.segment Code
+  // main
+main: {
+    // data.w = 0x1234
+    // [0] *((word*)&data) = $1234 -- _deref_pwuc1=vwuc2 
+    lda #<$1234
+    sta data
+    lda #>$1234
+    sta data+1
+    // BYTE1(data.w)
+    // [1] main::$0 = byte1  *((word*)&data) -- vbuaa=_byte1__deref_pwuc1 
+    // SCREEN[0] = BYTE1(data.w)
+    // [2] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa 
+    sta SCREEN
+    // BYTE0(data.w)
+    // [3] main::$1 = byte0  *((word*)&data) -- vbuaa=_byte0__deref_pwuc1 
+    lda data
+    // SCREEN[1] = BYTE0(data.w)
+    // [4] *(SCREEN+1) = main::$1 -- _deref_pbuc1=vbuaa 
+    sta SCREEN+1
+    // main::@return
+    // }
+    // [5] return 
+    rts
+}
+  // File Data
+.segment Data
+  data: .byte $c
+  .fill 1, 0
+
diff --git a/src/test/ref/union-6.sym b/src/test/ref/union-6.sym
new file mode 100644
index 000000000..2b9b5a258
--- /dev/null
+++ b/src/test/ref/union-6.sym
@@ -0,0 +1,9 @@
+constant byte* const SCREEN = (byte*) 1024
+union Data data loadstore mem[2] = { b: $c }
+void main()
+byte~ main::$0 reg byte a 4.0
+byte~ main::$1 reg byte a 4.0
+
+reg byte a [ main::$0 ]
+reg byte a [ main::$1 ]
+mem[2] [ data ]