#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 addrinfo {
  int ai_addrlen;
  struct addrinfo *ai_addr;
  struct addrinfo *ai_next;
  int /*<<< orphan*/ ai_socktype;
  int /*<<< orphan*/ ai_family;
};

/* Variables and functions */
int /*<<< orphan*/ AF_INET6;
int /*<<< orphan*/ SOCK_DGRAM;
int /*<<< orphan*/ freeaddrinfo(struct addrinfo *);
char *get_sockname(struct addrinfo *);
scalar_t__ getaddrinfo(char *, char *, struct addrinfo *, struct addrinfo **);
void *malloc(int);
int /*<<< orphan*/ memcpy(struct addrinfo *, struct addrinfo *, int);
int /*<<< orphan*/ memset(struct addrinfo *, int /*<<< orphan*/, int);
char *get_ipv6_addr() {
  struct addrinfo hints;
  struct addrinfo *result, *resp;
  static struct addrinfo *cached = NULL;
  if (cached != NULL)
    return get_sockname(cached);
  memset(&hints, 0, sizeof(struct addrinfo));
  hints.ai_family = AF_INET6;
  hints.ai_socktype = SOCK_DGRAM;
  if (getaddrinfo("k.root-servers.net", "domain", &hints, &result) != 0) {
    return NULL;
  }
  for (resp = result; resp != NULL; resp = resp->ai_next) {
    char *addr_string = get_sockname(resp);
    if (!addr_string && result->ai_next != NULL)
      continue;
    if ((cached = malloc(sizeof(struct addrinfo))) == NULL)
      return NULL;
    memcpy(cached, resp, sizeof(struct addrinfo));
    if ((cached->ai_addr = malloc(resp->ai_addrlen)) == NULL) {
      cached = NULL;
      return NULL;
    }
    memcpy(cached->ai_addr, resp->ai_addr, resp->ai_addrlen);
    freeaddrinfo(result);
    return addr_string;
  }
  freeaddrinfo(result);
  return NULL;
}


x86 assembly (clang, -O0):
<get_ipv6_addr>:
push   %rbp
mov    %rsp,%rbp
sub    $0x40,%rsp
cmpq   $0x0,0x2ee8(%rip)
je     118b <get_ipv6_addr+0x2b>
mov    0x2edb(%rip),%rdi
call   1030 <get_sockname@plt>
mov    %rax,-0x8(%rbp)
jmp    12ef <get_ipv6_addr+0x18f>
lea    -0x28(%rbp),%rdi
xor    %esi,%esi
mov    $0x20,%edx
call   1040 <memset@plt>
mov    0x2e3e(%rip),%rax
mov    (%rax),%eax
mov    %eax,-0xc(%rbp)
mov    0x2e3a(%rip),%rax
mov    (%rax),%eax
mov    %eax,-0x10(%rbp)
lea    0xe46(%rip),%rdi
lea    0xe52(%rip),%rsi
lea    -0x28(%rbp),%rdx
lea    -0x30(%rbp),%rcx
call   1070 <getaddrinfo@plt>
cmp    $0x0,%rax
je     11e5 <get_ipv6_addr+0x85>
movq   $0x0,-0x8(%rbp)
jmp    12ef <get_ipv6_addr+0x18f>
mov    -0x30(%rbp),%rax
mov    %rax,-0x38(%rbp)
cmpq   $0x0,-0x38(%rbp)
je     12de <get_ipv6_addr+0x17e>
mov    -0x38(%rbp),%rdi
call   1030 <get_sockname@plt>
mov    %rax,-0x40(%rbp)
cmpq   $0x0,-0x40(%rbp)
jne    1224 <get_ipv6_addr+0xc4>
mov    -0x30(%rbp),%rax
cmpq   $0x0,0x10(%rax)
je     1224 <get_ipv6_addr+0xc4>
jmp    12cd <get_ipv6_addr+0x16d>
mov    $0x20,%edi
call   1060 <malloc@plt>
mov    %rax,0x2e23(%rip)
cmp    $0x0,%rax
jne    124c <get_ipv6_addr+0xec>
movq   $0x0,-0x8(%rbp)
jmp    12ef <get_ipv6_addr+0x18f>
mov    0x2e05(%rip),%rdi
mov    -0x38(%rbp),%rsi
mov    $0x20,%edx
call   1050 <memcpy@plt>
mov    -0x38(%rbp),%rax
mov    (%rax),%edi
call   1060 <malloc@plt>
mov    0x2de5(%rip),%rcx
mov    %rax,0x8(%rcx)
cmp    $0x0,%rax
jne    1299 <get_ipv6_addr+0x139>
movq   $0x0,0x2dcc(%rip)
movq   $0x0,-0x8(%rbp)
jmp    12ef <get_ipv6_addr+0x18f>
mov    0x2db8(%rip),%rax
mov    0x8(%rax),%rdi
mov    -0x38(%rbp),%rax
mov    0x8(%rax),%rsi
mov    -0x38(%rbp),%rax
mov    (%rax),%edx
call   1050 <memcpy@plt>
mov    -0x30(%rbp),%rdi
call   1080 <freeaddrinfo@plt>
mov    -0x40(%rbp),%rax
mov    %rax,-0x8(%rbp)
jmp    12ef <get_ipv6_addr+0x18f>
mov    -0x38(%rbp),%rax
mov    0x10(%rax),%rax
mov    %rax,-0x38(%rbp)
jmp    11ed <get_ipv6_addr+0x8d>
mov    -0x30(%rbp),%rdi
call   1080 <freeaddrinfo@plt>
movq   $0x0,-0x8(%rbp)
mov    -0x8(%rbp),%rax
add    $0x40,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<get_ipv6_addr>:
push   %rbp
push   %r14
push   %rbx
sub    $0x30,%rsp
mov    0x2ee9(%rip),%rdi
test   %rdi,%rdi
je     1181 <get_ipv6_addr+0x21>
add    $0x30,%rsp
pop    %rbx
pop    %r14
pop    %rbp
jmp    1030 <get_sockname@plt>
lea    0x10(%rsp),%rbx
xor    %r14d,%r14d
mov    %rbx,%rdi
xor    %esi,%esi
mov    $0x20,%edx
call   1040 <memset@plt>
mov    0x2e41(%rip),%rax
mov    (%rax),%eax
mov    %eax,0x2c(%rsp)
mov    0x2e3c(%rip),%rax
mov    (%rax),%eax
mov    %eax,0x28(%rsp)
lea    0xe47(%rip),%rdi
lea    0xe53(%rip),%rsi
lea    0x8(%rsp),%rcx
mov    %rbx,%rdx
call   1070 <getaddrinfo@plt>
test   %rax,%rax
jne    127a <get_ipv6_addr+0x11a>
mov    0x8(%rsp),%rbx
test   %rbx,%rbx
je     1270 <get_ipv6_addr+0x110>
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
mov    %rbx,%rdi
call   1030 <get_sockname@plt>
mov    %rax,%r14
test   %rax,%rax
jne    1217 <get_ipv6_addr+0xb7>
mov    0x8(%rsp),%rdi
cmpq   $0x0,0x10(%rdi)
je     1217 <get_ipv6_addr+0xb7>
mov    0x10(%rbx),%rbx
test   %rbx,%rbx
jne    11f0 <get_ipv6_addr+0x90>
jmp    1272 <get_ipv6_addr+0x112>
mov    $0x20,%edi
call   1060 <malloc@plt>
mov    %rax,0x2e30(%rip)
test   %rax,%rax
je     1277 <get_ipv6_addr+0x117>
mov    %rax,%rdi
mov    %rbx,%rsi
mov    $0x20,%edx
call   1050 <memcpy@plt>
mov    (%rbx),%ebp
mov    %ebp,%edi
call   1060 <malloc@plt>
mov    0x2e0b(%rip),%rcx
mov    %rax,0x8(%rcx)
test   %rax,%rax
je     1286 <get_ipv6_addr+0x126>
mov    0x8(%rbx),%rsi
mov    %rax,%rdi
mov    %ebp,%edx
call   1050 <memcpy@plt>
mov    0x8(%rsp),%rdi
call   1080 <freeaddrinfo@plt>
jmp    127a <get_ipv6_addr+0x11a>
xor    %edi,%edi
call   1080 <freeaddrinfo@plt>
xor    %r14d,%r14d
mov    %r14,%rax
add    $0x30,%rsp
pop    %rbx
pop    %r14
pop    %rbp
ret
movq   $0x0,0x2dc7(%rip)
jmp    1277 <get_ipv6_addr+0x117>

LLVM IR (-O0):
%struct.addrinfo = type { i32, %struct.addrinfo*, %struct.addrinfo*, i32, i32 }
@get_ipv6_addr.cached = internal global %struct.addrinfo* null
@AF_INET6 = global i32 0
@SOCK_DGRAM = global i32 0
@.str = [19 x i8] c"k.root-servers.net\00"
@.str.1 = [7 x i8] c"domain\00"
define i8* @get_ipv6_addr() {
%1 = alloca i8*
%2 = alloca %struct.addrinfo
%3 = alloca %struct.addrinfo*
%4 = alloca %struct.addrinfo*
%5 = alloca i8*
%6 = load %struct.addrinfo*, %struct.addrinfo** @get_ipv6_addr.cached
%7 = icmp ne %struct.addrinfo* %6, null
br i1 %7, label %8, label %11
8: ; preds = %0
%9 = load %struct.addrinfo*, %struct.addrinfo** @get_ipv6_addr.cached
%10 = call i8* @get_sockname(%struct.addrinfo* %9)
store i8* %10, i8** %1
br label %75
11: ; preds = %0
%12 = call i32 @memset(%struct.addrinfo* %2, i32 0, i32 32)
%13 = load i32, i32* @AF_INET6
%14 = getelementptr inbounds %struct.addrinfo, %struct.addrinfo* %2, i32 0, i32 4
store i32 %13, i32* %14
%15 = load i32, i32* @SOCK_DGRAM
%16 = getelementptr inbounds %struct.addrinfo, %struct.addrinfo* %2, i32 0, i32 3
store i32 %15, i32* %16
%17 = call i64 @getaddrinfo(i8* getelementptr inbounds ([19 x i8], [19 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.1, i64 0, i64 0), %struct.addrinfo* %2, %struct.addrinfo** %3)
%18 = icmp ne i64 %17, 0
br i1 %18, label %19, label %20
19: ; preds = %11
store i8* null, i8** %1
br label %75
20: ; preds = %11
%21 = load %struct.addrinfo*, %struct.addrinfo** %3
store %struct.addrinfo* %21, %struct.addrinfo** %4
br label %22
22: ; preds = %68, %20
%23 = load %struct.addrinfo*, %struct.addrinfo** %4
%24 = icmp ne %struct.addrinfo* %23, null
br i1 %24, label %25, label %72
25: ; preds = %22
%26 = load %struct.addrinfo*, %struct.addrinfo** %4
%27 = call i8* @get_sockname(%struct.addrinfo* %26)
store i8* %27, i8** %5
%28 = load i8*, i8** %5
%29 = icmp ne i8* %28, null
br i1 %29, label %36, label %30
30: ; preds = %25
%31 = load %struct.addrinfo*, %struct.addrinfo** %3
%32 = getelementptr inbounds %struct.addrinfo, %struct.addrinfo* %31, i32 0, i32 2
%33 = load %struct.addrinfo*, %struct.addrinfo** %32
%34 = icmp ne %struct.addrinfo* %33, null
br i1 %34, label %35, label %36
35: ; preds = %30
br label %68
36: ; preds = %30, %25
%37 = call i8* @malloc(i32 32)
%38 = bitcast i8* %37 to %struct.addrinfo*
store %struct.addrinfo* %38, %struct.addrinfo** @get_ipv6_addr.cached
%39 = icmp eq %struct.addrinfo* %38, null
br i1 %39, label %40, label %41
40: ; preds = %36
store i8* null, i8** %1
br label %75
41: ; preds = %36
%42 = load %struct.addrinfo*, %struct.addrinfo** @get_ipv6_addr.cached
%43 = load %struct.addrinfo*, %struct.addrinfo** %4
%44 = call i32 @memcpy(%struct.addrinfo* %42, %struct.addrinfo* %43, i32 32)
%45 = load %struct.addrinfo*, %struct.addrinfo** %4
%46 = getelementptr inbounds %struct.addrinfo, %struct.addrinfo* %45, i32 0, i32 0
%47 = load i32, i32* %46
%48 = call i8* @malloc(i32 %47)
%49 = bitcast i8* %48 to %struct.addrinfo*
%50 = load %struct.addrinfo*, %struct.addrinfo** @get_ipv6_addr.cached
%51 = getelementptr inbounds %struct.addrinfo, %struct.addrinfo* %50, i32 0, i32 1
store %struct.addrinfo* %49, %struct.addrinfo** %51
%52 = icmp eq %struct.addrinfo* %49, null
br i1 %52, label %53, label %54
53: ; preds = %41
store %struct.addrinfo* null, %struct.addrinfo** @get_ipv6_addr.cached
store i8* null, i8** %1
br label %75
54: ; preds = %41
%55 = load %struct.addrinfo*, %struct.addrinfo** @get_ipv6_addr.cached
%56 = getelementptr inbounds %struct.addrinfo, %struct.addrinfo* %55, i32 0, i32 1
%57 = load %struct.addrinfo*, %struct.addrinfo** %56
%58 = load %struct.addrinfo*, %struct.addrinfo** %4
%59 = getelementptr inbounds %struct.addrinfo, %struct.addrinfo* %58, i32 0, i32 1
%60 = load %struct.addrinfo*, %struct.addrinfo** %59
%61 = load %struct.addrinfo*, %struct.addrinfo** %4
%62 = getelementptr inbounds %struct.addrinfo, %struct.addrinfo* %61, i32 0, i32 0
%63 = load i32, i32* %62
%64 = call i32 @memcpy(%struct.addrinfo* %57, %struct.addrinfo* %60, i32 %63)
%65 = load %struct.addrinfo*, %struct.addrinfo** %3
%66 = call i32 @freeaddrinfo(%struct.addrinfo* %65)
%67 = load i8*, i8** %5
store i8* %67, i8** %1
br label %75
68: ; preds = %35
%69 = load %struct.addrinfo*, %struct.addrinfo** %4
%70 = getelementptr inbounds %struct.addrinfo, %struct.addrinfo* %69, i32 0, i32 2
%71 = load %struct.addrinfo*, %struct.addrinfo** %70
store %struct.addrinfo* %71, %struct.addrinfo** %4
br label %22
72: ; preds = %22
%73 = load %struct.addrinfo*, %struct.addrinfo** %3
%74 = call i32 @freeaddrinfo(%struct.addrinfo* %73)
store i8* null, i8** %1
br label %75
75: ; preds = %72, %54, %53, %40, %19, %8
%76 = load i8*, i8** %1
ret i8* %76
}

LLVM IR (-O2):
%struct.addrinfo = type { i32, %struct.addrinfo*, %struct.addrinfo*, i32, i32 }
@get_ipv6_addr.cached = internal unnamed_addr global %struct.addrinfo* null
@AF_INET6 = global i32 0
@SOCK_DGRAM = global i32 0
@.str = [19 x i8] c"k.root-servers.net\00"
@.str.1 = [7 x i8] c"domain\00"
define i8* @get_ipv6_addr() {
%1 = alloca %struct.addrinfo
%2 = alloca %struct.addrinfo*
%3 = bitcast %struct.addrinfo* %1 to i8*
%4 = bitcast %struct.addrinfo** %2 to i8*
%5 = load %struct.addrinfo*, %struct.addrinfo** @get_ipv6_addr.cached
%6 = icmp eq %struct.addrinfo* %5, null
br i1 %6, label %9, label %7
7: ; preds = %0
%8 = tail call i8* @get_sockname(%struct.addrinfo* %5)
br label %57
9: ; preds = %0
%10 = call i32 @memset(%struct.addrinfo* %1, i32 0, i32 32)
%11 = load i32, i32* @AF_INET6
%12 = getelementptr inbounds %struct.addrinfo, %struct.addrinfo* %1, i64 0, i32 4
store i32 %11, i32* %12
%13 = load i32, i32* @SOCK_DGRAM
%14 = getelementptr inbounds %struct.addrinfo, %struct.addrinfo* %1, i64 0, i32 3
store i32 %13, i32* %14
%15 = call i64 @getaddrinfo(i8* getelementptr inbounds ([19 x i8], [19 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.1, i64 0, i64 0), %struct.addrinfo* %1, %struct.addrinfo** %2)
%16 = icmp eq i64 %15, 0
br i1 %16, label %17, label %57
17: ; preds = %9
%18 = load %struct.addrinfo*, %struct.addrinfo** %2
%19 = icmp eq %struct.addrinfo* %18, null
br i1 %19, label %54, label %20
20: ; preds = %17, %50
%21 = phi %struct.addrinfo* [ %52, %50 ], [ %18, %17 ]
%22 = call i8* @get_sockname(%struct.addrinfo* %21)
%23 = icmp eq i8* %22, null
br i1 %23, label %24, label %29
24: ; preds = %20
%25 = load %struct.addrinfo*, %struct.addrinfo** %2
%26 = getelementptr inbounds %struct.addrinfo, %struct.addrinfo* %25, i64 0, i32 2
%27 = load %struct.addrinfo*, %struct.addrinfo** %26
%28 = icmp eq %struct.addrinfo* %27, null
br i1 %28, label %29, label %50
29: ; preds = %24, %20
%30 = call dereferenceable_or_null(32) i8* @malloc(i32 32)
store i8* %30, i8** bitcast (%struct.addrinfo** @get_ipv6_addr.cached to i8**)
%31 = icmp eq i8* %30, null
br i1 %31, label %57, label %32
32: ; preds = %29
%33 = bitcast i8* %30 to %struct.addrinfo*
%34 = call i32 @memcpy(%struct.addrinfo* %33, %struct.addrinfo* %21, i32 32)
%35 = getelementptr inbounds %struct.addrinfo, %struct.addrinfo* %21, i64 0, i32 0
%36 = load i32, i32* %35
%37 = call i8* @malloc(i32 %36)
%38 = load %struct.addrinfo*, %struct.addrinfo** @get_ipv6_addr.cached
%39 = getelementptr inbounds %struct.addrinfo, %struct.addrinfo* %38, i64 0, i32 1
%40 = bitcast %struct.addrinfo** %39 to i8**
store i8* %37, i8** %40
%41 = icmp eq i8* %37, null
br i1 %41, label %42, label %43
42: ; preds = %32
store %struct.addrinfo* null, %struct.addrinfo** @get_ipv6_addr.cached
br label %57
43: ; preds = %32
%44 = bitcast i8* %37 to %struct.addrinfo*
%45 = getelementptr inbounds %struct.addrinfo, %struct.addrinfo* %21, i64 0, i32 1
%46 = load %struct.addrinfo*, %struct.addrinfo** %45
%47 = call i32 @memcpy(%struct.addrinfo* %44, %struct.addrinfo* %46, i32 %36)
%48 = load %struct.addrinfo*, %struct.addrinfo** %2
%49 = call i32 @freeaddrinfo(%struct.addrinfo* %48)
br label %57
50: ; preds = %24
%51 = getelementptr inbounds %struct.addrinfo, %struct.addrinfo* %21, i64 0, i32 2
%52 = load %struct.addrinfo*, %struct.addrinfo** %51
%53 = icmp eq %struct.addrinfo* %52, null
br i1 %53, label %54, label %20
54: ; preds = %50, %17
%55 = phi %struct.addrinfo* [ null, %17 ], [ %25, %50 ]
%56 = call i32 @freeaddrinfo(%struct.addrinfo* %55)
br label %57
57: ; preds = %29, %42, %43, %9, %54, %7
%58 = phi i8* [ %8, %7 ], [ null, %54 ], [ null, %9 ], [ null, %29 ], [ null, %42 ], [ %22, %43 ]
ret i8* %58
}