#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 buffer {
  int dummy;
};

/* Variables and functions */
char *buffer_copy(struct buffer *);
char *buffer_cstr(struct buffer *);
int /*<<< orphan*/ buffer_end(struct buffer *);
struct buffer *buffer_fromstr(char const *, int, int /*<<< orphan*/);
int buffer_popc(struct buffer *);
int /*<<< orphan*/ buffer_removeslice(struct buffer *, int, int);
int /*<<< orphan*/ free(char *);
int /*<<< orphan*/ printf(char *, ...);
int test_fromstr_pop_copy_remove(void) {
  const char str[] = "this is the fromstr test. this is about stuff.";
  struct buffer *b = buffer_fromstr(str, sizeof str - 1, 0);
  char *c;
  int ret = -1;
  if (b == NULL)
    return -1;
  printf("pop: %c\n", buffer_popc(b));
  c = buffer_copy(b);
  if (c == NULL)
    goto error;
  buffer_removeslice(b, 12, 20);
  printf("<%s> / %s\n", buffer_cstr(b), c);
  free(c);
  ret = 1;
error:
  buffer_end(b);
  return ret;
}


x86 assembly (clang, -O0):
<test_fromstr_pop_copy_remove>:
push   %rbp
mov    %rsp,%rbp
sub    $0x60,%rsp
lea    -0x40(%rbp),%rdi
lea    0xe5d(%rip),%rsi
mov    $0x2f,%edx
call   1070 <memcpy@plt>
lea    -0x40(%rbp),%rdi
mov    $0x2e,%esi
xor    %edx,%edx
call   1080 <buffer_fromstr@plt>
mov    %rax,-0x48(%rbp)
movl   $0xffffffff,-0x54(%rbp)
cmpq   $0x0,-0x48(%rbp)
jne    11df <test_fromstr_pop_copy_remove+0x4f>
movl   $0xffffffff,-0x4(%rbp)
jmp    1265 <test_fromstr_pop_copy_remove+0xd5>
mov    -0x48(%rbp),%rdi
call   10b0 <buffer_popc@plt>
mov    %eax,%esi
lea    0xe3e(%rip),%rdi
mov    $0x0,%al
call   1060 <printf@plt>
mov    -0x48(%rbp),%rdi
call   10a0 <buffer_copy@plt>
mov    %rax,-0x50(%rbp)
cmpq   $0x0,-0x50(%rbp)
jne    1215 <test_fromstr_pop_copy_remove+0x85>
jmp    1256 <test_fromstr_pop_copy_remove+0xc6>
mov    -0x48(%rbp),%rdi
mov    $0xc,%esi
mov    $0x14,%edx
call   1090 <buffer_removeslice@plt>
mov    -0x48(%rbp),%rdi
call   1040 <buffer_cstr@plt>
mov    %rax,%rsi
mov    -0x50(%rbp),%rdx
lea    0xdf9(%rip),%rdi
mov    $0x0,%al
call   1060 <printf@plt>
mov    -0x50(%rbp),%rdi
call   1030 <free@plt>
movl   $0x1,-0x54(%rbp)
mov    -0x48(%rbp),%rdi
call   1050 <buffer_end@plt>
mov    -0x54(%rbp),%eax
mov    %eax,-0x4(%rbp)
mov    -0x4(%rbp),%eax
add    $0x60,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<test_fromstr_pop_copy_remove>:
push   %rbp
push   %r14
push   %rbx
sub    $0x30,%rsp
movups 0xe90(%rip),%xmm0
movups %xmm0,0x1f(%rsp)
movaps 0xe75(%rip),%xmm0
movaps %xmm0,0x10(%rsp)
movaps 0xe59(%rip),%xmm0
movaps %xmm0,(%rsp)
mov    %rsp,%rdi
mov    $0x2e,%esi
xor    %edx,%edx
call   1070 <buffer_fromstr@plt>
test   %rax,%rax
je     1227 <test_fromstr_pop_copy_remove+0xa7>
mov    %rax,%rbx
mov    %rax,%rdi
call   10a0 <buffer_popc@plt>
lea    0xe5e(%rip),%rdi
mov    %eax,%esi
xor    %eax,%eax
call   1060 <printf@plt>
mov    %rbx,%rdi
call   1090 <buffer_copy@plt>
test   %rax,%rax
je     122e <test_fromstr_pop_copy_remove+0xae>
mov    %rax,%r14
mov    %rbx,%rdi
mov    $0xc,%esi
mov    $0x14,%edx
call   1080 <buffer_removeslice@plt>
mov    %rbx,%rdi
call   1040 <buffer_cstr@plt>
lea    0xe2d(%rip),%rdi
mov    %rax,%rsi
mov    %r14,%rdx
xor    %eax,%eax
call   1060 <printf@plt>
mov    %r14,%rdi
call   1030 <free@plt>
mov    $0x1,%ebp
jmp    1233 <test_fromstr_pop_copy_remove+0xb3>
mov    $0xffffffff,%ebp
jmp    123b <test_fromstr_pop_copy_remove+0xbb>
mov    $0xffffffff,%ebp
mov    %rbx,%rdi
call   1050 <buffer_end@plt>
mov    %ebp,%eax
add    $0x30,%rsp
pop    %rbx
pop    %r14
pop    %rbp
ret

LLVM IR (-O0):
%struct.buffer = type { i32 }
@__const.test_fromstr_pop_copy_remove.str = [47 x i8] c"this is the fromstr test. this is about stuff.\00"
@.str = [9 x i8] c"pop: %c\0A\00"
@.str.1 = [11 x i8] c"<%s> / %s\0A\00"
define i32 @test_fromstr_pop_copy_remove() {
%1 = alloca i32
%2 = alloca [47 x i8]
%3 = alloca %struct.buffer*
%4 = alloca i8*
%5 = alloca i32
%6 = bitcast [47 x i8]* %2 to i8*
%7 = getelementptr inbounds [47 x i8], [47 x i8]* %2, i64 0, i64 0
%8 = call %struct.buffer* @buffer_fromstr(i8* %7, i32 46, i32 0)
store %struct.buffer* %8, %struct.buffer** %3
store i32 -1, i32* %5
%9 = load %struct.buffer*, %struct.buffer** %3
%10 = icmp eq %struct.buffer* %9, null
br i1 %10, label %11, label %12
11: ; preds = %0
store i32 -1, i32* %1
br label %34
12: ; preds = %0
%13 = load %struct.buffer*, %struct.buffer** %3
%14 = call i32 @buffer_popc(%struct.buffer* %13)
%15 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i64 0, i64 0), i32 %14)
%16 = load %struct.buffer*, %struct.buffer** %3
%17 = call i8* @buffer_copy(%struct.buffer* %16)
store i8* %17, i8** %4
%18 = load i8*, i8** %4
%19 = icmp eq i8* %18, null
br i1 %19, label %20, label %21
20: ; preds = %12
br label %30
21: ; preds = %12
%22 = load %struct.buffer*, %struct.buffer** %3
%23 = call i32 @buffer_removeslice(%struct.buffer* %22, i32 12, i32 20)
%24 = load %struct.buffer*, %struct.buffer** %3
%25 = call i8* @buffer_cstr(%struct.buffer* %24)
%26 = load i8*, i8** %4
%27 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.1, i64 0, i64 0), i8* %25, i8* %26)
%28 = load i8*, i8** %4
%29 = call i32 @free(i8* %28)
store i32 1, i32* %5
br label %30
30: ; preds = %21, %20
%31 = load %struct.buffer*, %struct.buffer** %3
%32 = call i32 @buffer_end(%struct.buffer* %31)
%33 = load i32, i32* %5
store i32 %33, i32* %1
br label %34
34: ; preds = %30, %11
%35 = load i32, i32* %1
ret i32 %35
}

LLVM IR (-O2):
%struct.buffer = type { i32 }
@__const.test_fromstr_pop_copy_remove.str = [47 x i8] c"this is the fromstr test. this is about stuff.\00"
@.str = [9 x i8] c"pop: %c\0A\00"
@.str.1 = [11 x i8] c"<%s> / %s\0A\00"
define i32 @test_fromstr_pop_copy_remove() {
%1 = alloca [47 x i8]
%2 = getelementptr inbounds [47 x i8], [47 x i8]* %1, i64 0, i64 0
%3 = call %struct.buffer* @buffer_fromstr(i8* %2, i32 46, i32 0)
%4 = icmp eq %struct.buffer* %3, null
br i1 %4, label %18, label %5
5: ; preds = %0
%6 = call i32 @buffer_popc(%struct.buffer* %3)
%7 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i64 0, i64 0), i32 %6)
%8 = call i8* @buffer_copy(%struct.buffer* %3)
%9 = icmp eq i8* %8, null
br i1 %9, label %15, label %10
10: ; preds = %5
%11 = call i32 @buffer_removeslice(%struct.buffer* %3, i32 12, i32 20)
%12 = call i8* @buffer_cstr(%struct.buffer* %3)
%13 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([11 x i8], [11 x i8]* @.str.1, i64 0, i64 0), i8* %12, i8* %8)
%14 = call i32 @free(i8* %8)
br label %15
15: ; preds = %5, %10
%16 = phi i32 [ -1, %5 ], [ 1, %10 ]
%17 = call i32 @buffer_end(%struct.buffer* %3)
br label %18
18: ; preds = %0, %15
%19 = phi i32 [ %16, %15 ], [ -1, %0 ]
ret i32 %19
}