#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */
struct sockaddr_un {
  int dummy;
};
typedef struct sockaddr_storage {
  int sa_family;
  int ss_family;
} const sockaddr_storage;
struct sockaddr_in6 {
  int dummy;
};
struct sockaddr_in {
  int dummy;
};
struct sockaddr {
  int sa_family;
  int ss_family;
};

/* Variables and functions */
#define AF_INET 130
#define AF_INET6 129
#define AF_UNIX 128
int /*<<< orphan*/ assert(struct sockaddr_storage const *);
int /*<<< orphan*/ memset(struct sockaddr_storage const *, int /*<<< orphan*/,
                          int);
int /*<<< orphan*/
tow_internet6_socket_address_copy(struct sockaddr_in6 *,
                                  struct sockaddr_in6 const *);
int /*<<< orphan*/ tow_internet_socket_address_copy(struct sockaddr_in *,
                                                    struct sockaddr_in const *);
int /*<<< orphan*/ tow_unix_socket_address_copy(struct sockaddr_un *,
                                                struct sockaddr_un const *);
void tow_socket_address_copy(struct sockaddr_storage *destination,
                             struct sockaddr const *source) {
  assert(destination);
  assert(source);
  switch (source->sa_family) {
  case AF_INET:
    tow_internet_socket_address_copy((struct sockaddr_in *)destination,
                                     (struct sockaddr_in const *)source);
    break;
  case AF_INET6:
    tow_internet6_socket_address_copy((struct sockaddr_in6 *)destination,
                                      (struct sockaddr_in6 const *)source);
    break;
  case AF_UNIX:
    tow_unix_socket_address_copy((struct sockaddr_un *)destination,
                                 (struct sockaddr_un const *)source);
    break;
  default:
    memset(destination, 0, sizeof(struct sockaddr_storage));
    destination->ss_family = source->sa_family;
    break;
  }
}


x86 assembly (clang, -O0):
<tow_socket_address_copy>:
push   %rbp
mov    %rsp,%rbp
sub    $0x20,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    -0x8(%rbp),%rdi
call   1050 <assert@plt>
mov    -0x10(%rbp),%rdi
call   1050 <assert@plt>
mov    -0x10(%rbp),%rax
mov    (%rax),%eax
mov    %eax,-0x14(%rbp)
sub    $0x80,%eax
je     11d5 <tow_socket_address_copy+0x85>
jmp    118b <tow_socket_address_copy+0x3b>
mov    -0x14(%rbp),%eax
sub    $0x81,%eax
je     11c3 <tow_socket_address_copy+0x73>
jmp    119e <tow_socket_address_copy+0x4e>
mov    -0x14(%rbp),%eax
sub    $0x82,%eax
jne    11e7 <tow_socket_address_copy+0x97>
jmp    11b1 <tow_socket_address_copy+0x61>
mov    -0x8(%rbp),%rdi
mov    -0x10(%rbp),%rsi
call   1030 <tow_internet_socket_address_copy@plt>
jmp    1204 <tow_socket_address_copy+0xb4>
mov    -0x8(%rbp),%rdi
mov    -0x10(%rbp),%rsi
call   1060 <tow_internet6_socket_address_copy@plt>
jmp    1204 <tow_socket_address_copy+0xb4>
mov    -0x8(%rbp),%rdi
mov    -0x10(%rbp),%rsi
call   1070 <tow_unix_socket_address_copy@plt>
jmp    1204 <tow_socket_address_copy+0xb4>
mov    -0x8(%rbp),%rdi
xor    %esi,%esi
mov    $0x8,%edx
call   1040 <memset@plt>
mov    -0x10(%rbp),%rax
mov    (%rax),%ecx
mov    -0x8(%rbp),%rax
mov    %ecx,0x4(%rax)
add    $0x20,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<tow_socket_address_copy>:
push   %r14
push   %rbx
push   %rax
mov    %rsi,%rbx
mov    %rdi,%r14
call   1050 <assert@plt>
mov    %rbx,%rdi
call   1050 <assert@plt>
mov    (%rbx),%eax
cmp    $0x80,%eax
je     1190 <tow_socket_address_copy+0x40>
cmp    $0x81,%eax
je     11a2 <tow_socket_address_copy+0x52>
cmp    $0x82,%eax
jne    11b4 <tow_socket_address_copy+0x64>
mov    %r14,%rdi
mov    %rbx,%rsi
add    $0x8,%rsp
pop    %rbx
pop    %r14
jmp    1030 <tow_internet_socket_address_copy@plt>
mov    %r14,%rdi
mov    %rbx,%rsi
add    $0x8,%rsp
pop    %rbx
pop    %r14
jmp    1070 <tow_unix_socket_address_copy@plt>
mov    %r14,%rdi
mov    %rbx,%rsi
add    $0x8,%rsp
pop    %rbx
pop    %r14
jmp    1060 <tow_internet6_socket_address_copy@plt>
mov    %r14,%rdi
xor    %esi,%esi
mov    $0x8,%edx
call   1040 <memset@plt>
mov    (%rbx),%eax
mov    %eax,0x4(%r14)
add    $0x8,%rsp
pop    %rbx
pop    %r14
ret

LLVM IR (-O0):
%struct.sockaddr_storage = type { i32, i32 }
%struct.sockaddr = type { i32, i32 }
%struct.sockaddr_in = type { i32 }
%struct.sockaddr_in6 = type { i32 }
%struct.sockaddr_un = type { i32 }
define void @tow_socket_address_copy(%struct.sockaddr_storage* %0, %struct.sockaddr* %1) {
%3 = alloca %struct.sockaddr_storage*
%4 = alloca %struct.sockaddr*
store %struct.sockaddr_storage* %0, %struct.sockaddr_storage** %3
store %struct.sockaddr* %1, %struct.sockaddr** %4
%5 = load %struct.sockaddr_storage*, %struct.sockaddr_storage** %3
%6 = call i32 @assert(%struct.sockaddr_storage* %5)
%7 = load %struct.sockaddr*, %struct.sockaddr** %4
%8 = bitcast %struct.sockaddr* %7 to %struct.sockaddr_storage*
%9 = call i32 @assert(%struct.sockaddr_storage* %8)
%10 = load %struct.sockaddr*, %struct.sockaddr** %4
%11 = getelementptr inbounds %struct.sockaddr, %struct.sockaddr* %10, i32 0, i32 0
%12 = load i32, i32* %11
switch i32 %12, label %31 [
i32 130, label %13
i32 129, label %19
i32 128, label %25
]
13: ; preds = %2
%14 = load %struct.sockaddr_storage*, %struct.sockaddr_storage** %3
%15 = bitcast %struct.sockaddr_storage* %14 to %struct.sockaddr_in*
%16 = load %struct.sockaddr*, %struct.sockaddr** %4
%17 = bitcast %struct.sockaddr* %16 to %struct.sockaddr_in*
%18 = call i32 @tow_internet_socket_address_copy(%struct.sockaddr_in* %15, %struct.sockaddr_in* %17)
br label %39
19: ; preds = %2
%20 = load %struct.sockaddr_storage*, %struct.sockaddr_storage** %3
%21 = bitcast %struct.sockaddr_storage* %20 to %struct.sockaddr_in6*
%22 = load %struct.sockaddr*, %struct.sockaddr** %4
%23 = bitcast %struct.sockaddr* %22 to %struct.sockaddr_in6*
%24 = call i32 @tow_internet6_socket_address_copy(%struct.sockaddr_in6* %21, %struct.sockaddr_in6* %23)
br label %39
25: ; preds = %2
%26 = load %struct.sockaddr_storage*, %struct.sockaddr_storage** %3
%27 = bitcast %struct.sockaddr_storage* %26 to %struct.sockaddr_un*
%28 = load %struct.sockaddr*, %struct.sockaddr** %4
%29 = bitcast %struct.sockaddr* %28 to %struct.sockaddr_un*
%30 = call i32 @tow_unix_socket_address_copy(%struct.sockaddr_un* %27, %struct.sockaddr_un* %29)
br label %39
31: ; preds = %2
%32 = load %struct.sockaddr_storage*, %struct.sockaddr_storage** %3
%33 = call i32 @memset(%struct.sockaddr_storage* %32, i32 0, i32 8)
%34 = load %struct.sockaddr*, %struct.sockaddr** %4
%35 = getelementptr inbounds %struct.sockaddr, %struct.sockaddr* %34, i32 0, i32 0
%36 = load i32, i32* %35
%37 = load %struct.sockaddr_storage*, %struct.sockaddr_storage** %3
%38 = getelementptr inbounds %struct.sockaddr_storage, %struct.sockaddr_storage* %37, i32 0, i32 1
store i32 %36, i32* %38
br label %39
39: ; preds = %31, %25, %19, %13
ret void
}

LLVM IR (-O2):
%struct.sockaddr_storage = type { i32, i32 }
%struct.sockaddr = type { i32, i32 }
%struct.sockaddr_in = type { i32 }
%struct.sockaddr_in6 = type { i32 }
%struct.sockaddr_un = type { i32 }
define void @tow_socket_address_copy(%struct.sockaddr_storage* %0, %struct.sockaddr* %1) {
%3 = tail call i32 @assert(%struct.sockaddr_storage* %0)
%4 = bitcast %struct.sockaddr* %1 to %struct.sockaddr_storage*
%5 = tail call i32 @assert(%struct.sockaddr_storage* %4)
%6 = getelementptr inbounds %struct.sockaddr, %struct.sockaddr* %1, i64 0, i32 0
%7 = load i32, i32* %6
switch i32 %7, label %20 [
i32 130, label %8
i32 129, label %12
i32 128, label %16
]
8: ; preds = %2
%9 = bitcast %struct.sockaddr_storage* %0 to %struct.sockaddr_in*
%10 = bitcast %struct.sockaddr* %1 to %struct.sockaddr_in*
%11 = tail call i32 @tow_internet_socket_address_copy(%struct.sockaddr_in* %9, %struct.sockaddr_in* %10)
br label %24
12: ; preds = %2
%13 = bitcast %struct.sockaddr_storage* %0 to %struct.sockaddr_in6*
%14 = bitcast %struct.sockaddr* %1 to %struct.sockaddr_in6*
%15 = tail call i32 @tow_internet6_socket_address_copy(%struct.sockaddr_in6* %13, %struct.sockaddr_in6* %14)
br label %24
16: ; preds = %2
%17 = bitcast %struct.sockaddr_storage* %0 to %struct.sockaddr_un*
%18 = bitcast %struct.sockaddr* %1 to %struct.sockaddr_un*
%19 = tail call i32 @tow_unix_socket_address_copy(%struct.sockaddr_un* %17, %struct.sockaddr_un* %18)
br label %24
20: ; preds = %2
%21 = tail call i32 @memset(%struct.sockaddr_storage* %0, i32 0, i32 8)
%22 = load i32, i32* %6
%23 = getelementptr inbounds %struct.sockaddr_storage, %struct.sockaddr_storage* %0, i64 0, i32 1
store i32 %22, i32* %23
br label %24
24: ; preds = %20, %16, %12, %8
ret void
}