#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 */
typedef int /*<<< orphan*/ u_int8_t;
struct in_addr {
  int /*<<< orphan*/ s_addr;
};
struct ether_header {
  void *ether_type;
  int /*<<< orphan*/ ether_shost;
  int /*<<< orphan*/ ether_dhost;
};
struct ether_arp {
  int arp_hln;
  int arp_pln;
  scalar_t__ arp_tpa;
  scalar_t__ arp_spa;
  scalar_t__ arp_sha;
  void *arp_op;
  void *arp_pro;
  void *arp_hrd;
};
struct ether_addr {
  int /*<<< orphan*/ ether_addr_octet;
};

/* Variables and functions */
int /*<<< orphan*/ ARPHRD_ETHER;
int /*<<< orphan*/ ARPOP_REQUEST;
int /*<<< orphan*/ ETHERTYPE_ARP;
int /*<<< orphan*/ ETHERTYPE_IP;
int ETH_ALEN;
void *htons(int /*<<< orphan*/);
int /*<<< orphan*/ memcpy(void *, void *, int);
int /*<<< orphan*/ memset(void *, int, int);
void arp_generate_packet(struct in_addr sip, struct in_addr tip,
                         struct ether_addr smac, u_int8_t *packet) {
  struct ether_header *eth_header;
  struct ether_arp *arp_header;
  eth_header = (struct ether_header *)packet;
  memset((void *)&eth_header->ether_dhost, 0xff, ETH_ALEN);
  memcpy((void *)&eth_header->ether_shost, (void *)&smac.ether_addr_octet,
         ETH_ALEN);
  eth_header->ether_type = htons(ETHERTYPE_ARP);
  arp_header = (struct ether_arp *)(packet + sizeof(struct ether_header));
  arp_header->arp_hrd = htons(ARPHRD_ETHER);
  arp_header->arp_pro = htons(ETHERTYPE_IP);
  arp_header->arp_hln = ETH_ALEN;
  arp_header->arp_pln = 4;
  arp_header->arp_op = htons(ARPOP_REQUEST);
  memcpy((void *)arp_header->arp_sha, (void *)&smac.ether_addr_octet, ETH_ALEN);
  memcpy((void *)arp_header->arp_spa, (void *)&sip.s_addr, 4);
  memcpy((void *)arp_header->arp_tpa, (void *)&tip.s_addr, 4);
}


x86 assembly (clang, -O0):
<arp_generate_packet>:
push   %rbp
mov    %rsp,%rbp
sub    $0x30,%rsp
mov    %edi,-0x8(%rbp)
mov    %esi,-0x10(%rbp)
mov    %edx,-0x18(%rbp)
mov    %rcx,-0x20(%rbp)
mov    -0x20(%rbp),%rax
mov    %rax,-0x28(%rbp)
mov    -0x28(%rbp),%rdi
add    $0xc,%rdi
mov    0x2e84(%rip),%rax
mov    (%rax),%edx
mov    $0xff,%esi
call   1040 <memset@plt>
mov    -0x28(%rbp),%rdi
add    $0x8,%rdi
lea    -0x18(%rbp),%rsi
mov    0x2e65(%rip),%rax
mov    (%rax),%edx
call   1050 <memcpy@plt>
mov    0x2e37(%rip),%rax
mov    (%rax),%edi
call   1030 <htons@plt>
mov    %rax,%rcx
mov    -0x28(%rbp),%rax
mov    %rcx,(%rax)
mov    -0x20(%rbp),%rax
add    $0x40,%rax
mov    %rax,-0x30(%rbp)
mov    0x2e23(%rip),%rax
mov    (%rax),%edi
call   1030 <htons@plt>
mov    %rax,%rcx
mov    -0x30(%rbp),%rax
mov    %rcx,0x30(%rax)
mov    0x2e22(%rip),%rax
mov    (%rax),%edi
call   1030 <htons@plt>
mov    %rax,%rcx
mov    -0x30(%rbp),%rax
mov    %rcx,0x28(%rax)
mov    0x2e01(%rip),%rax
mov    (%rax),%ecx
mov    -0x30(%rbp),%rax
mov    %ecx,(%rax)
mov    -0x30(%rbp),%rax
movl   $0x4,0x4(%rax)
mov    0x2ddf(%rip),%rax
mov    (%rax),%edi
call   1030 <htons@plt>
mov    %rax,%rcx
mov    -0x30(%rbp),%rax
mov    %rcx,0x20(%rax)
mov    -0x30(%rbp),%rax
mov    0x18(%rax),%rdi
lea    -0x18(%rbp),%rsi
mov    0x2dc2(%rip),%rax
mov    (%rax),%edx
call   1050 <memcpy@plt>
mov    -0x30(%rbp),%rax
mov    0x10(%rax),%rdi
lea    -0x8(%rbp),%rsi
mov    $0x4,%edx
call   1050 <memcpy@plt>
mov    -0x30(%rbp),%rax
mov    0x8(%rax),%rdi
lea    -0x10(%rbp),%rsi
mov    $0x4,%edx
call   1050 <memcpy@plt>
add    $0x30,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<arp_generate_packet>:
push   %r15
push   %r14
push   %rbx
sub    $0x20,%rsp
mov    %rcx,%rbx
mov    %edi,0x18(%rsp)
mov    %esi,0x10(%rsp)
mov    %edx,0x8(%rsp)
lea    0xc(%rcx),%rdi
mov    0x2e8d(%rip),%r15
mov    (%r15),%edx
mov    $0xff,%esi
call   1040 <memset@plt>
lea    0x8(%rbx),%rdi
mov    (%r15),%edx
lea    0x8(%rsp),%r14
mov    %r14,%rsi
call   1050 <memcpy@plt>
mov    0x2e45(%rip),%rax
mov    (%rax),%edi
call   1030 <htons@plt>
mov    %rax,(%rbx)
mov    0x2e44(%rip),%rax
mov    (%rax),%edi
call   1030 <htons@plt>
mov    %rax,0x70(%rbx)
mov    0x2e4a(%rip),%rax
mov    (%rax),%edi
call   1030 <htons@plt>
mov    %rax,0x68(%rbx)
mov    (%r15),%eax
mov    %eax,0x40(%rbx)
movl   $0x4,0x44(%rbx)
mov    0x2e1b(%rip),%rax
mov    (%rax),%edi
call   1030 <htons@plt>
mov    %rax,0x60(%rbx)
mov    0x58(%rbx),%rdi
mov    (%r15),%edx
mov    %r14,%rsi
call   1050 <memcpy@plt>
mov    0x50(%rbx),%rdi
lea    0x18(%rsp),%rsi
mov    $0x4,%edx
call   1050 <memcpy@plt>
mov    0x48(%rbx),%rdi
lea    0x10(%rsp),%rsi
mov    $0x4,%edx
call   1050 <memcpy@plt>
add    $0x20,%rsp
pop    %rbx
pop    %r14
pop    %r15
ret

LLVM IR (-O0):
%struct.in_addr = type { i32 }
%struct.ether_addr = type { i32 }
%struct.ether_header = type { i8*, i32, i32 }
%struct.ether_arp = type { i32, i32, i64, i64, i64, i8*, i8*, i8* }
@ETH_ALEN = global i32 0
@ETHERTYPE_ARP = global i32 0
@ARPHRD_ETHER = global i32 0
@ETHERTYPE_IP = global i32 0
@ARPOP_REQUEST = global i32 0
define void @arp_generate_packet(i32 %0, i32 %1, i32 %2, i32* %3) {
%5 = alloca %struct.in_addr
%6 = alloca %struct.in_addr
%7 = alloca %struct.ether_addr
%8 = alloca i32*
%9 = alloca %struct.ether_header*
%10 = alloca %struct.ether_arp*
%11 = getelementptr inbounds %struct.in_addr, %struct.in_addr* %5, i32 0, i32 0
store i32 %0, i32* %11
%12 = getelementptr inbounds %struct.in_addr, %struct.in_addr* %6, i32 0, i32 0
store i32 %1, i32* %12
%13 = getelementptr inbounds %struct.ether_addr, %struct.ether_addr* %7, i32 0, i32 0
store i32 %2, i32* %13
store i32* %3, i32** %8
%14 = load i32*, i32** %8
%15 = bitcast i32* %14 to %struct.ether_header*
store %struct.ether_header* %15, %struct.ether_header** %9
%16 = load %struct.ether_header*, %struct.ether_header** %9
%17 = getelementptr inbounds %struct.ether_header, %struct.ether_header* %16, i32 0, i32 2
%18 = bitcast i32* %17 to i8*
%19 = load i32, i32* @ETH_ALEN
%20 = call i32 @memset(i8* %18, i32 255, i32 %19)
%21 = load %struct.ether_header*, %struct.ether_header** %9
%22 = getelementptr inbounds %struct.ether_header, %struct.ether_header* %21, i32 0, i32 1
%23 = bitcast i32* %22 to i8*
%24 = getelementptr inbounds %struct.ether_addr, %struct.ether_addr* %7, i32 0, i32 0
%25 = bitcast i32* %24 to i8*
%26 = load i32, i32* @ETH_ALEN
%27 = call i32 @memcpy(i8* %23, i8* %25, i32 %26)
%28 = load i32, i32* @ETHERTYPE_ARP
%29 = call i8* @htons(i32 %28)
%30 = load %struct.ether_header*, %struct.ether_header** %9
%31 = getelementptr inbounds %struct.ether_header, %struct.ether_header* %30, i32 0, i32 0
store i8* %29, i8** %31
%32 = load i32*, i32** %8
%33 = getelementptr inbounds i32, i32* %32, i64 16
%34 = bitcast i32* %33 to %struct.ether_arp*
store %struct.ether_arp* %34, %struct.ether_arp** %10
%35 = load i32, i32* @ARPHRD_ETHER
%36 = call i8* @htons(i32 %35)
%37 = load %struct.ether_arp*, %struct.ether_arp** %10
%38 = getelementptr inbounds %struct.ether_arp, %struct.ether_arp* %37, i32 0, i32 7
store i8* %36, i8** %38
%39 = load i32, i32* @ETHERTYPE_IP
%40 = call i8* @htons(i32 %39)
%41 = load %struct.ether_arp*, %struct.ether_arp** %10
%42 = getelementptr inbounds %struct.ether_arp, %struct.ether_arp* %41, i32 0, i32 6
store i8* %40, i8** %42
%43 = load i32, i32* @ETH_ALEN
%44 = load %struct.ether_arp*, %struct.ether_arp** %10
%45 = getelementptr inbounds %struct.ether_arp, %struct.ether_arp* %44, i32 0, i32 0
store i32 %43, i32* %45
%46 = load %struct.ether_arp*, %struct.ether_arp** %10
%47 = getelementptr inbounds %struct.ether_arp, %struct.ether_arp* %46, i32 0, i32 1
store i32 4, i32* %47
%48 = load i32, i32* @ARPOP_REQUEST
%49 = call i8* @htons(i32 %48)
%50 = load %struct.ether_arp*, %struct.ether_arp** %10
%51 = getelementptr inbounds %struct.ether_arp, %struct.ether_arp* %50, i32 0, i32 5
store i8* %49, i8** %51
%52 = load %struct.ether_arp*, %struct.ether_arp** %10
%53 = getelementptr inbounds %struct.ether_arp, %struct.ether_arp* %52, i32 0, i32 4
%54 = load i64, i64* %53
%55 = inttoptr i64 %54 to i8*
%56 = getelementptr inbounds %struct.ether_addr, %struct.ether_addr* %7, i32 0, i32 0
%57 = bitcast i32* %56 to i8*
%58 = load i32, i32* @ETH_ALEN
%59 = call i32 @memcpy(i8* %55, i8* %57, i32 %58)
%60 = load %struct.ether_arp*, %struct.ether_arp** %10
%61 = getelementptr inbounds %struct.ether_arp, %struct.ether_arp* %60, i32 0, i32 3
%62 = load i64, i64* %61
%63 = inttoptr i64 %62 to i8*
%64 = getelementptr inbounds %struct.in_addr, %struct.in_addr* %5, i32 0, i32 0
%65 = bitcast i32* %64 to i8*
%66 = call i32 @memcpy(i8* %63, i8* %65, i32 4)
%67 = load %struct.ether_arp*, %struct.ether_arp** %10
%68 = getelementptr inbounds %struct.ether_arp, %struct.ether_arp* %67, i32 0, i32 2
%69 = load i64, i64* %68
%70 = inttoptr i64 %69 to i8*
%71 = getelementptr inbounds %struct.in_addr, %struct.in_addr* %6, i32 0, i32 0
%72 = bitcast i32* %71 to i8*
%73 = call i32 @memcpy(i8* %70, i8* %72, i32 4)
ret void
}

LLVM IR (-O2):
%struct.in_addr = type { i32 }
%struct.ether_addr = type { i32 }
@ETH_ALEN = global i32 0
@ETHERTYPE_ARP = global i32 0
@ARPHRD_ETHER = global i32 0
@ETHERTYPE_IP = global i32 0
@ARPOP_REQUEST = global i32 0
define void @arp_generate_packet(i32 %0, i32 %1, i32 %2, i32* %3) {
%5 = alloca %struct.in_addr
%6 = alloca %struct.in_addr
%7 = alloca %struct.ether_addr
%8 = getelementptr inbounds %struct.in_addr, %struct.in_addr* %5, i64 0, i32 0
store i32 %0, i32* %8
%9 = getelementptr inbounds %struct.in_addr, %struct.in_addr* %6, i64 0, i32 0
store i32 %1, i32* %9
%10 = getelementptr inbounds %struct.ether_addr, %struct.ether_addr* %7, i64 0, i32 0
store i32 %2, i32* %10
%11 = getelementptr inbounds i32, i32* %3, i64 3
%12 = bitcast i32* %11 to i8*
%13 = load i32, i32* @ETH_ALEN
%14 = tail call i32 @memset(i8* %12, i32 255, i32 %13)
%15 = getelementptr inbounds i32, i32* %3, i64 2
%16 = bitcast i32* %15 to i8*
%17 = bitcast %struct.ether_addr* %7 to i8*
%18 = load i32, i32* @ETH_ALEN
%19 = call i32 @memcpy(i8* %16, i8* %17, i32 %18)
%20 = load i32, i32* @ETHERTYPE_ARP
%21 = call i8* @htons(i32 %20)
%22 = bitcast i32* %3 to i8**
store i8* %21, i8** %22
%23 = getelementptr inbounds i32, i32* %3, i64 16
%24 = load i32, i32* @ARPHRD_ETHER
%25 = call i8* @htons(i32 %24)
%26 = getelementptr inbounds i32, i32* %3, i64 28
%27 = bitcast i32* %26 to i8**
store i8* %25, i8** %27
%28 = load i32, i32* @ETHERTYPE_IP
%29 = call i8* @htons(i32 %28)
%30 = getelementptr inbounds i32, i32* %3, i64 26
%31 = bitcast i32* %30 to i8**
store i8* %29, i8** %31
%32 = load i32, i32* @ETH_ALEN
store i32 %32, i32* %23
%33 = getelementptr inbounds i32, i32* %3, i64 17
store i32 4, i32* %33
%34 = load i32, i32* @ARPOP_REQUEST
%35 = call i8* @htons(i32 %34)
%36 = getelementptr inbounds i32, i32* %3, i64 24
%37 = bitcast i32* %36 to i8**
store i8* %35, i8** %37
%38 = getelementptr inbounds i32, i32* %3, i64 22
%39 = bitcast i32* %38 to i64*
%40 = load i64, i64* %39
%41 = inttoptr i64 %40 to i8*
%42 = load i32, i32* @ETH_ALEN
%43 = call i32 @memcpy(i8* %41, i8* %17, i32 %42)
%44 = getelementptr inbounds i32, i32* %3, i64 20
%45 = bitcast i32* %44 to i64*
%46 = load i64, i64* %45
%47 = inttoptr i64 %46 to i8*
%48 = bitcast %struct.in_addr* %5 to i8*
%49 = call i32 @memcpy(i8* %47, i8* %48, i32 4)
%50 = getelementptr inbounds i32, i32* %3, i64 18
%51 = bitcast i32* %50 to i64*
%52 = load i64, i64* %51
%53 = inttoptr i64 %52 to i8*
%54 = bitcast %struct.in_addr* %6 to i8*
%55 = call i32 @memcpy(i8* %53, i8* %54, i32 4)
ret void
}