int test1(void) {
  struct A {
    char text[4];
  } a = {"Hei"};
  struct B {
    int i;
  } b = {42};
  union U {
    struct A a;
    struct B b;
  } u1 = {a}, u2 = {.b = b};
  struct C {
    union U u;
  } s1 = {u1}, s2 = {a}, s3 = {"Oi"};
  printf("%s\n", u1.a.text);
  printf("%d\n", u2.b.i);
  printf("%s\n", s1.u.a.text);
  printf("%s\n", s2.u.a.text);
  printf("%s\n", s3.u.a.text);
  return 0;
}


x86 assembly (clang, -O0):
<test1>:
push   %rbp
mov    %rsp,%rbp
sub    $0x40,%rsp
mov    0xee2(%rip),%eax
mov    %eax,-0x8(%rbp)
mov    0xedd(%rip),%eax
mov    %eax,-0x10(%rbp)
mov    -0x8(%rbp),%eax
mov    %eax,-0x18(%rbp)
mov    -0x10(%rbp),%eax
mov    %eax,-0x20(%rbp)
mov    -0x18(%rbp),%eax
mov    %eax,-0x28(%rbp)
mov    -0x8(%rbp),%eax
mov    %eax,-0x30(%rbp)
mov    0xec0(%rip),%eax
mov    %eax,-0x38(%rbp)
lea    -0x18(%rbp),%rsi
lea    0xeb6(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
mov    -0x20(%rbp),%esi
lea    0xea9(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
lea    -0x28(%rbp),%rsi
lea    0xe93(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
lea    -0x30(%rbp),%rsi
lea    0xe81(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
lea    -0x38(%rbp),%rsi
lea    0xe6f(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
xor    %eax,%eax
add    $0x40,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<test1>:
sub    $0x28,%rsp
movl   $0x696548,0x20(%rsp)
movl   $0x696548,0x18(%rsp)
movl   $0x696548,0x10(%rsp)
movl   $0x694f,0x8(%rsp)
lea    0x20(%rsp),%rdi
call   1030 <puts@plt>
lea    0xeab(%rip),%rdi
mov    $0x2a,%esi
xor    %eax,%eax
call   1040 <printf@plt>
lea    0x18(%rsp),%rdi
call   1030 <puts@plt>
lea    0x10(%rsp),%rdi
call   1030 <puts@plt>
lea    0x8(%rsp),%rdi
call   1030 <puts@plt>
xor    %eax,%eax
add    $0x28,%rsp
ret

LLVM IR (-O0):
%struct.A = type { [4 x i8] }
%struct.B = type { i32 }
%union.U = type { %struct.B }
%struct.C = type { %union.U }
@__const.test1.a = %struct.A { [4 x i8] c"Hei\00" }
@__const.test1.b = %struct.B { i32 42 }
@__const.test1.s3 = { { %struct.A } } { { %struct.A } { %struct.A { [4 x i8] c"Oi\00\00" } } }
@.str = [4 x i8] c"%s\0A\00"
@.str.1 = [4 x i8] c"%d\0A\00"
define i32 @test1() {
%1 = alloca %struct.A
%2 = alloca %struct.B
%3 = alloca %union.U
%4 = alloca %union.U
%5 = alloca %struct.C
%6 = alloca %struct.C
%7 = alloca %struct.C
%8 = bitcast %struct.A* %1 to i8*
%9 = bitcast %struct.B* %2 to i8*
%10 = bitcast %union.U* %3 to %struct.A*
%11 = bitcast %struct.A* %10 to i8*
%12 = bitcast %struct.A* %1 to i8*
%13 = bitcast %union.U* %4 to %struct.B*
%14 = bitcast %struct.B* %13 to i8*
%15 = bitcast %struct.B* %2 to i8*
%16 = getelementptr inbounds %struct.C, %struct.C* %5, i32 0, i32 0
%17 = bitcast %union.U* %16 to i8*
%18 = bitcast %union.U* %3 to i8*
%19 = getelementptr inbounds %struct.C, %struct.C* %6, i32 0, i32 0
%20 = bitcast %union.U* %19 to %struct.A*
%21 = bitcast %struct.A* %20 to i8*
%22 = bitcast %struct.A* %1 to i8*
%23 = bitcast %struct.C* %7 to i8*
%24 = bitcast %union.U* %3 to %struct.A*
%25 = getelementptr inbounds %struct.A, %struct.A* %24, i32 0, i32 0
%26 = getelementptr inbounds [4 x i8], [4 x i8]* %25, i64 0, i64 0
%27 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i8* %26)
%28 = bitcast %union.U* %4 to %struct.B*
%29 = getelementptr inbounds %struct.B, %struct.B* %28, i32 0, i32 0
%30 = load i32, i32* %29
%31 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.1, i64 0, i64 0), i32 %30)
%32 = getelementptr inbounds %struct.C, %struct.C* %5, i32 0, i32 0
%33 = bitcast %union.U* %32 to %struct.A*
%34 = getelementptr inbounds %struct.A, %struct.A* %33, i32 0, i32 0
%35 = getelementptr inbounds [4 x i8], [4 x i8]* %34, i64 0, i64 0
%36 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i8* %35)
%37 = getelementptr inbounds %struct.C, %struct.C* %6, i32 0, i32 0
%38 = bitcast %union.U* %37 to %struct.A*
%39 = getelementptr inbounds %struct.A, %struct.A* %38, i32 0, i32 0
%40 = getelementptr inbounds [4 x i8], [4 x i8]* %39, i64 0, i64 0
%41 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i8* %40)
%42 = getelementptr inbounds %struct.C, %struct.C* %7, i32 0, i32 0
%43 = bitcast %union.U* %42 to %struct.A*
%44 = getelementptr inbounds %struct.A, %struct.A* %43, i32 0, i32 0
%45 = getelementptr inbounds [4 x i8], [4 x i8]* %44, i64 0, i64 0
%46 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i8* %45)
ret i32 0
}

LLVM IR (-O2):
%union.U = type { %struct.B }
%struct.B = type { i32 }
%struct.C = type { %union.U }
@.str.1 = [4 x i8] c"%d\0A\00"
define i32 @test1() {
%1 = alloca %union.U
%2 = alloca %struct.C
%3 = alloca %struct.C
%4 = alloca %struct.C
%5 = bitcast %union.U* %1 to i8*
%6 = getelementptr inbounds %union.U, %union.U* %1, i64 0, i32 0, i32 0
store i32 6907208, i32* %6
%7 = bitcast %struct.C* %2 to i8*
%8 = getelementptr inbounds %struct.C, %struct.C* %2, i64 0, i32 0, i32 0, i32 0
store i32 6907208, i32* %8
%9 = bitcast %struct.C* %3 to i8*
%10 = getelementptr inbounds %struct.C, %struct.C* %3, i64 0, i32 0, i32 0, i32 0
store i32 6907208, i32* %10
%11 = bitcast %struct.C* %4 to i8*
%12 = getelementptr inbounds %struct.C, %struct.C* %4, i64 0, i32 0, i32 0, i32 0
store i32 26959, i32* %12
%13 = call i32 @puts(i8* %5)
%14 = tail call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([4 x i8], [4 x i8]* @.str.1, i64 0, i64 0), i32 42)
%15 = call i32 @puts(i8* %7)
%16 = call i32 @puts(i8* %9)
%17 = call i32 @puts(i8* %11)
ret i32 0
}