#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_nl {
  int dummy;
};
struct rtmsg {
  int rtm_family;
};
struct nlmsghdr {
  int nlmsg_flags;
  int /*<<< orphan*/ nlmsg_len;
  int /*<<< orphan*/ nlmsg_type;
};
struct msghdr {
  int member_1;
  int member_3;
  int /*<<< orphan*/ member_6;
  int /*<<< orphan*/ member_5;
  int /*<<< orphan*/ *member_4;
  struct iovec *member_2;
  struct sockaddr_nl *member_0;
};
struct iovec {
  int /*<<< orphan*/ member_1;
  struct nlmsghdr *member_0;
};

/* Variables and functions */
scalar_t__ NLMSG_DATA(struct nlmsghdr *);
int /*<<< orphan*/ NLMSG_LENGTH(int);
int NLM_F_REQUEST;
int NLM_F_ROOT;
int /*<<< orphan*/ RTM_GETROUTE;
int /*<<< orphan*/ memset(char *, int /*<<< orphan*/, int);
int sendmsg(int, struct msghdr *, int /*<<< orphan*/);
int get_gateway(int fd, struct sockaddr_nl *sa, int domain) {
  char buf[4096];
  memset(buf, 0, 4096);
  struct nlmsghdr *nl;
  nl = (struct nlmsghdr *)buf;
  nl->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
  nl->nlmsg_type = RTM_GETROUTE;
  nl->nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;
  struct rtmsg *rt;
  rt = (struct rtmsg *)NLMSG_DATA(nl);
  rt->rtm_family = domain;
  struct iovec iov = {nl, nl->nlmsg_len};
  struct msghdr msg = {sa, sizeof(*sa), &iov, 1, NULL, 0, 0};
  int r = sendmsg(fd, &msg, 0);
  return (r < 0) ? -1 : 0;
}


x86 assembly (clang, -O0):
<get_gateway>:
push   %rbp
mov    %rsp,%rbp
sub    $0x1070,%rsp
mov    %edi,-0x4(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
lea    -0x1020(%rbp),%rdi
xor    %esi,%esi
mov    $0x1000,%edx
call   1050 <memset@plt>
lea    -0x1020(%rbp),%rax
mov    %rax,-0x1028(%rbp)
mov    $0x4,%edi
call   1040 <NLMSG_LENGTH@plt>
mov    %eax,%ecx
mov    -0x1028(%rbp),%rax
mov    %ecx,0x4(%rax)
mov    0x2e4d(%rip),%rax
mov    (%rax),%ecx
mov    -0x1028(%rbp),%rax
mov    %ecx,0x8(%rax)
mov    0x2e42(%rip),%rax
mov    (%rax),%ecx
mov    0x2e29(%rip),%rax
or     (%rax),%ecx
mov    -0x1028(%rbp),%rax
mov    %ecx,(%rax)
mov    -0x1028(%rbp),%rdi
call   1060 <NLMSG_DATA@plt>
mov    %rax,-0x1030(%rbp)
mov    -0x14(%rbp),%ecx
mov    -0x1030(%rbp),%rax
mov    %ecx,(%rax)
mov    -0x1028(%rbp),%rax
mov    %eax,-0x1040(%rbp)
mov    -0x1028(%rbp),%rax
movslq 0x4(%rax),%rax
mov    %rax,-0x1038(%rbp)
mov    -0x10(%rbp),%rax
mov    %eax,-0x1068(%rbp)
movl   $0x4,-0x1064(%rbp)
lea    -0x1040(%rbp),%rax
mov    %eax,-0x1060(%rbp)
movl   $0x1,-0x105c(%rbp)
movq   $0x0,-0x1058(%rbp)
movq   $0x0,-0x1050(%rbp)
movq   $0x0,-0x1048(%rbp)
mov    -0x4(%rbp),%edi
lea    -0x1068(%rbp),%rsi
xor    %edx,%edx
call   1030 <sendmsg@plt>
mov    %eax,-0x106c(%rbp)
mov    -0x106c(%rbp),%edx
xor    %eax,%eax
mov    $0xffffffff,%ecx
cmp    $0x0,%edx
cmovl  %ecx,%eax
add    $0x1070,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<get_gateway>:
push   %rbp
push   %r15
push   %r14
push   %rbx
sub    $0x1048,%rsp
mov    %edx,%ebp
mov    %rsi,%r15
mov    %edi,%r14d
lea    0x40(%rsp),%rbx
mov    %rbx,%rdi
xor    %esi,%esi
mov    $0x1000,%edx
call   1050 <memset@plt>
mov    $0x4,%edi
call   1040 <NLMSG_LENGTH@plt>
mov    %eax,0x44(%rsp)
mov    0x2e62(%rip),%rax
mov    (%rax),%eax
mov    %eax,0x48(%rsp)
mov    0x2e5d(%rip),%rax
mov    0x2e46(%rip),%rcx
mov    (%rcx),%ecx
or     (%rax),%ecx
mov    %ecx,0x40(%rsp)
mov    %rbx,%rdi
call   1060 <NLMSG_DATA@plt>
mov    %ebp,(%rax)
mov    %ebx,0x8(%rsp)
movslq 0x44(%rsp),%rax
mov    %rax,0x10(%rsp)
mov    %r15d,0x18(%rsp)
movl   $0x4,0x1c(%rsp)
lea    0x8(%rsp),%rax
mov    %eax,0x20(%rsp)
movl   $0x1,0x24(%rsp)
xorps  %xmm0,%xmm0
movups %xmm0,0x28(%rsp)
movq   $0x0,0x38(%rsp)
lea    0x18(%rsp),%rsi
mov    %r14d,%edi
xor    %edx,%edx
call   1030 <sendmsg@plt>
sar    $0x1f,%eax
add    $0x1048,%rsp
pop    %rbx
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
%struct.sockaddr_nl = type { i32 }
%struct.nlmsghdr = type { i32, i32, i32 }
%struct.rtmsg = type { i32 }
%struct.iovec = type { i32, %struct.nlmsghdr* }
%struct.msghdr = type { i32, i32, i32, i32, i32*, %struct.iovec*, %struct.sockaddr_nl* }
@RTM_GETROUTE = global i32 0
@NLM_F_REQUEST = global i32 0
@NLM_F_ROOT = global i32 0
define i32 @get_gateway(i32 %0, %struct.sockaddr_nl* %1, i32 %2) {
%4 = alloca i32
%5 = alloca %struct.sockaddr_nl*
%6 = alloca i32
%7 = alloca [4096 x i8]
%8 = alloca %struct.nlmsghdr*
%9 = alloca %struct.rtmsg*
%10 = alloca %struct.iovec
%11 = alloca %struct.msghdr
%12 = alloca i32
store i32 %0, i32* %4
store %struct.sockaddr_nl* %1, %struct.sockaddr_nl** %5
store i32 %2, i32* %6
%13 = getelementptr inbounds [4096 x i8], [4096 x i8]* %7, i64 0, i64 0
%14 = call i32 @memset(i8* %13, i32 0, i32 4096)
%15 = getelementptr inbounds [4096 x i8], [4096 x i8]* %7, i64 0, i64 0
%16 = bitcast i8* %15 to %struct.nlmsghdr*
store %struct.nlmsghdr* %16, %struct.nlmsghdr** %8
%17 = call i32 @NLMSG_LENGTH(i32 4)
%18 = load %struct.nlmsghdr*, %struct.nlmsghdr** %8
%19 = getelementptr inbounds %struct.nlmsghdr, %struct.nlmsghdr* %18, i32 0, i32 1
store i32 %17, i32* %19
%20 = load i32, i32* @RTM_GETROUTE
%21 = load %struct.nlmsghdr*, %struct.nlmsghdr** %8
%22 = getelementptr inbounds %struct.nlmsghdr, %struct.nlmsghdr* %21, i32 0, i32 2
store i32 %20, i32* %22
%23 = load i32, i32* @NLM_F_REQUEST
%24 = load i32, i32* @NLM_F_ROOT
%25 = or i32 %23, %24
%26 = load %struct.nlmsghdr*, %struct.nlmsghdr** %8
%27 = getelementptr inbounds %struct.nlmsghdr, %struct.nlmsghdr* %26, i32 0, i32 0
store i32 %25, i32* %27
%28 = load %struct.nlmsghdr*, %struct.nlmsghdr** %8
%29 = call i64 @NLMSG_DATA(%struct.nlmsghdr* %28)
%30 = inttoptr i64 %29 to %struct.rtmsg*
store %struct.rtmsg* %30, %struct.rtmsg** %9
%31 = load i32, i32* %6
%32 = load %struct.rtmsg*, %struct.rtmsg** %9
%33 = getelementptr inbounds %struct.rtmsg, %struct.rtmsg* %32, i32 0, i32 0
store i32 %31, i32* %33
%34 = getelementptr inbounds %struct.iovec, %struct.iovec* %10, i32 0, i32 0
%35 = load %struct.nlmsghdr*, %struct.nlmsghdr** %8
%36 = ptrtoint %struct.nlmsghdr* %35 to i32
store i32 %36, i32* %34
%37 = getelementptr inbounds %struct.iovec, %struct.iovec* %10, i32 0, i32 1
%38 = load %struct.nlmsghdr*, %struct.nlmsghdr** %8
%39 = getelementptr inbounds %struct.nlmsghdr, %struct.nlmsghdr* %38, i32 0, i32 1
%40 = load i32, i32* %39
%41 = sext i32 %40 to i64
%42 = inttoptr i64 %41 to %struct.nlmsghdr*
store %struct.nlmsghdr* %42, %struct.nlmsghdr** %37
%43 = getelementptr inbounds %struct.msghdr, %struct.msghdr* %11, i32 0, i32 0
%44 = load %struct.sockaddr_nl*, %struct.sockaddr_nl** %5
%45 = ptrtoint %struct.sockaddr_nl* %44 to i32
store i32 %45, i32* %43
%46 = getelementptr inbounds %struct.msghdr, %struct.msghdr* %11, i32 0, i32 1
store i32 4, i32* %46
%47 = getelementptr inbounds %struct.msghdr, %struct.msghdr* %11, i32 0, i32 2
%48 = ptrtoint %struct.iovec* %10 to i32
store i32 %48, i32* %47
%49 = getelementptr inbounds %struct.msghdr, %struct.msghdr* %11, i32 0, i32 3
store i32 1, i32* %49
%50 = getelementptr inbounds %struct.msghdr, %struct.msghdr* %11, i32 0, i32 4
store i32* null, i32** %50
%51 = getelementptr inbounds %struct.msghdr, %struct.msghdr* %11, i32 0, i32 5
store %struct.iovec* null, %struct.iovec** %51
%52 = getelementptr inbounds %struct.msghdr, %struct.msghdr* %11, i32 0, i32 6
store %struct.sockaddr_nl* null, %struct.sockaddr_nl** %52
%53 = load i32, i32* %4
%54 = call i32 @sendmsg(i32 %53, %struct.msghdr* %11, i32 0)
store i32 %54, i32* %12
%55 = load i32, i32* %12
%56 = icmp slt i32 %55, 0
%57 = zext i1 %56 to i64
%58 = select i1 %56, i32 -1, i32 0
ret i32 %58
}

LLVM IR (-O2):
%struct.sockaddr_nl = type { i32 }
%struct.iovec = type { i32, %struct.nlmsghdr* }
%struct.nlmsghdr = type { i32, i32, i32 }
%struct.msghdr = type { i32, i32, i32, i32, i32*, %struct.iovec*, %struct.sockaddr_nl* }
%struct.rtmsg = type { i32 }
@RTM_GETROUTE = global i32 0
@NLM_F_REQUEST = global i32 0
@NLM_F_ROOT = global i32 0
define i32 @get_gateway(i32 %0, %struct.sockaddr_nl* %1, i32 %2) {
%4 = alloca [4096 x i8]
%5 = alloca %struct.iovec
%6 = alloca %struct.msghdr
%7 = getelementptr inbounds [4096 x i8], [4096 x i8]* %4, i64 0, i64 0
%8 = call i32 @memset(i8* %7, i32 0, i32 4096)
%9 = bitcast [4096 x i8]* %4 to %struct.nlmsghdr*
%10 = call i32 @NLMSG_LENGTH(i32 4)
%11 = getelementptr inbounds [4096 x i8], [4096 x i8]* %4, i64 0, i64 4
%12 = bitcast i8* %11 to i32*
store i32 %10, i32* %12
%13 = load i32, i32* @RTM_GETROUTE
%14 = getelementptr inbounds [4096 x i8], [4096 x i8]* %4, i64 0, i64 8
%15 = bitcast i8* %14 to i32*
store i32 %13, i32* %15
%16 = load i32, i32* @NLM_F_REQUEST
%17 = load i32, i32* @NLM_F_ROOT
%18 = or i32 %17, %16
%19 = bitcast [4096 x i8]* %4 to i32*
store i32 %18, i32* %19
%20 = call i64 @NLMSG_DATA(%struct.nlmsghdr* %9)
%21 = inttoptr i64 %20 to %struct.rtmsg*
%22 = getelementptr inbounds %struct.rtmsg, %struct.rtmsg* %21, i64 0, i32 0
store i32 %2, i32* %22
%23 = bitcast %struct.iovec* %5 to i8*
%24 = getelementptr inbounds %struct.iovec, %struct.iovec* %5, i64 0, i32 0
%25 = ptrtoint [4096 x i8]* %4 to i64
%26 = trunc i64 %25 to i32
store i32 %26, i32* %24
%27 = getelementptr inbounds %struct.iovec, %struct.iovec* %5, i64 0, i32 1
%28 = load i32, i32* %12
%29 = sext i32 %28 to i64
%30 = inttoptr i64 %29 to %struct.nlmsghdr*
store %struct.nlmsghdr* %30, %struct.nlmsghdr** %27
%31 = bitcast %struct.msghdr* %6 to i8*
%32 = getelementptr inbounds %struct.msghdr, %struct.msghdr* %6, i64 0, i32 0
%33 = ptrtoint %struct.sockaddr_nl* %1 to i64
%34 = trunc i64 %33 to i32
store i32 %34, i32* %32
%35 = getelementptr inbounds %struct.msghdr, %struct.msghdr* %6, i64 0, i32 1
store i32 4, i32* %35
%36 = getelementptr inbounds %struct.msghdr, %struct.msghdr* %6, i64 0, i32 2
%37 = ptrtoint %struct.iovec* %5 to i64
%38 = trunc i64 %37 to i32
store i32 %38, i32* %36
%39 = getelementptr inbounds %struct.msghdr, %struct.msghdr* %6, i64 0, i32 3
store i32 1, i32* %39
%40 = getelementptr inbounds %struct.msghdr, %struct.msghdr* %6, i64 0, i32 4
%41 = bitcast i32** %40 to i8*
%42 = call i32 @sendmsg(i32 %0, %struct.msghdr* %6, i32 0)
%43 = ashr i32 %42, 31
ret i32 %43
}