#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 */

/* Variables and functions */
int /*<<< orphan*/ assert(int);
scalar_t__ calloc(int, size_t);
int /*<<< orphan*/ memset(char *, int /*<<< orphan*/, size_t);
scalar_t__ realloc(size_t *, size_t);
void _ProtoBufString(char **str, const void *data, size_t dataLen) {
  if (data || dataLen == 0) {
    if (!*str)
      do {
        size_t _array_cap = (dataLen + 1);
        assert(_array_cap >= 0);
        (*str) = (void *)((size_t *)calloc(1, _array_cap * sizeof(*(*str)) +
                                                  sizeof(size_t) * 2) +
                          2);
        assert((*str) != NULL);
        (((size_t *)(*str))[-2]) = _array_cap;
        (((size_t *)(*str))[-1]) = 0;
      } while (0);
    do {
      assert((*str) != NULL);
      memset((*str), 0, (((size_t *)(*str))[-1]) * sizeof(*(*str)));
      (((size_t *)(*str))[-1]) = 0;
    } while (0);
    do {
      assert((*str) != NULL);
      size_t _array_cnt = (dataLen), _array_i = (((size_t *)(*str))[-1]),
             _array_j = 0;
      assert(((const char *)data) != NULL || _array_cnt == 0);
      assert(_array_cnt >= 0);
      if (_array_i + _array_cnt > (((size_t *)(*str))[-2]))
        do {
          size_t _array_cap = ((_array_i + _array_cnt) * 3 / 2);
          assert((*str) != NULL);
          assert(_array_cap >= (((size_t *)(*str))[-1]));
          (*str) = (void *)((size_t *)realloc((size_t *)(*str) - 2,
                                              _array_cap * sizeof(*(*str)) +
                                                  sizeof(size_t) * 2) +
                            2);
          assert((*str) != NULL);
          if (_array_cap > (((size_t *)(*str))[-2]))
            memset((*str) + (((size_t *)(*str))[-2]), 0,
                   (_array_cap - (((size_t *)(*str))[-2])) * sizeof(*(*str)));
          (((size_t *)(*str))[-2]) = _array_cap;
        } while (0);
      while (_array_j < _array_cnt)
        (*str)[_array_i++] = ((const char *)data)[_array_j++];
      (((size_t *)(*str))[-1]) += _array_cnt;
    } while (0);
    do {
      assert((*str) != NULL);
      if ((((size_t *)(*str))[-1]) + 1 > (((size_t *)(*str))[-2]))
        do {
          size_t _array_cap = (((((size_t *)(*str))[-2]) + 1) * 3 / 2);
          assert((*str) != NULL);
          assert(_array_cap >= (((size_t *)(*str))[-1]));
          (*str) = (void *)((size_t *)realloc((size_t *)(*str) - 2,
                                              _array_cap * sizeof(*(*str)) +
                                                  sizeof(size_t) * 2) +
                            2);
          assert((*str) != NULL);
          if (_array_cap > (((size_t *)(*str))[-2]))
            memset((*str) + (((size_t *)(*str))[-2]), 0,
                   (_array_cap - (((size_t *)(*str))[-2])) * sizeof(*(*str)));
          (((size_t *)(*str))[-2]) = _array_cap;
        } while (0);
      (*str)[(((size_t *)(*str))[-1])++] = ('\0');
    } while (0);
  }
}


x86 assembly (clang, -O0):
<_ProtoBufString>:
push   %rbp
mov    %rsp,%rbp
sub    $0x50,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
cmpq   $0x0,-0x10(%rbp)
jne    116a <_ProtoBufString+0x2a>
cmpq   $0x0,-0x18(%rbp)
jne    1546 <_ProtoBufString+0x406>
mov    -0x8(%rbp),%rax
cmpq   $0x0,(%rax)
jne    11f7 <_ProtoBufString+0xb7>
jmp    117d <_ProtoBufString+0x3d>
mov    -0x18(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x20(%rbp)
cmpq   $0x0,-0x20(%rbp)
setae  %al
and    $0x1,%al
movzbl %al,%edi
call   1050 <assert@plt>
mov    -0x20(%rbp),%rsi
shl    $0x0,%rsi
add    $0x10,%rsi
mov    $0x1,%edi
call   1040 <calloc@plt>
mov    %rax,%rcx
add    $0x10,%rcx
mov    -0x8(%rbp),%rax
mov    %rcx,(%rax)
mov    -0x8(%rbp),%rax
cmpq   $0x0,(%rax)
setne  %al
and    $0x1,%al
movzbl %al,%edi
call   1050 <assert@plt>
mov    -0x20(%rbp),%rcx
mov    -0x8(%rbp),%rax
mov    (%rax),%rax
mov    %rcx,-0x10(%rax)
mov    -0x8(%rbp),%rax
mov    (%rax),%rax
movq   $0x0,-0x8(%rax)
jmp    11f7 <_ProtoBufString+0xb7>
jmp    11fc <_ProtoBufString+0xbc>
mov    -0x8(%rbp),%rax
cmpq   $0x0,(%rax)
setne  %al
and    $0x1,%al
movzbl %al,%edi
call   1050 <assert@plt>
mov    -0x8(%rbp),%rax
mov    (%rax),%rdi
mov    -0x8(%rbp),%rax
mov    (%rax),%rax
mov    -0x8(%rax),%rdx
shl    $0x0,%rdx
xor    %esi,%esi
call   1030 <memset@plt>
mov    -0x8(%rbp),%rax
mov    (%rax),%rax
movq   $0x0,-0x8(%rax)
jmp    1242 <_ProtoBufString+0x102>
mov    -0x8(%rbp),%rax
cmpq   $0x0,(%rax)
setne  %al
and    $0x1,%al
movzbl %al,%edi
call   1050 <assert@plt>
mov    -0x18(%rbp),%rax
mov    %rax,-0x28(%rbp)
mov    -0x8(%rbp),%rax
mov    (%rax),%rax
mov    -0x8(%rax),%rax
mov    %rax,-0x30(%rbp)
movq   $0x0,-0x38(%rbp)
mov    $0x1,%al
cmpq   $0x0,-0x10(%rbp)
mov    %al,-0x49(%rbp)
jne    1291 <_ProtoBufString+0x151>
cmpq   $0x0,-0x28(%rbp)
sete   %al
mov    %al,-0x49(%rbp)
mov    -0x49(%rbp),%al
and    $0x1,%al
movzbl %al,%edi
call   1050 <assert@plt>
cmpq   $0x0,-0x28(%rbp)
setae  %al
and    $0x1,%al
movzbl %al,%edi
call   1050 <assert@plt>
mov    -0x30(%rbp),%rax
add    -0x28(%rbp),%rax
mov    -0x8(%rbp),%rcx
mov    (%rcx),%rcx
cmp    -0x10(%rcx),%rax
jbe    13a7 <_ProtoBufString+0x267>
jmp    12ce <_ProtoBufString+0x18e>
mov    -0x30(%rbp),%rax
add    -0x28(%rbp),%rax
imul   $0x3,%rax,%rax
shr    $0x1,%rax
mov    %rax,-0x40(%rbp)
mov    -0x8(%rbp),%rax
cmpq   $0x0,(%rax)
setne  %al
and    $0x1,%al
movzbl %al,%edi
call   1050 <assert@plt>
mov    -0x40(%rbp),%rax
mov    -0x8(%rbp),%rcx
mov    (%rcx),%rcx
cmp    -0x8(%rcx),%rax
setae  %al
and    $0x1,%al
movzbl %al,%edi
call   1050 <assert@plt>
mov    -0x8(%rbp),%rax
mov    (%rax),%rdi
add    $0xfffffffffffffff0,%rdi
mov    -0x40(%rbp),%rsi
shl    $0x0,%rsi
add    $0x10,%rsi
call   1060 <realloc@plt>
mov    %rax,%rcx
add    $0x10,%rcx
mov    -0x8(%rbp),%rax
mov    %rcx,(%rax)
mov    -0x8(%rbp),%rax
cmpq   $0x0,(%rax)
setne  %al
and    $0x1,%al
movzbl %al,%edi
call   1050 <assert@plt>
mov    -0x40(%rbp),%rax
mov    -0x8(%rbp),%rcx
mov    (%rcx),%rcx
cmp    -0x10(%rcx),%rax
jbe    1393 <_ProtoBufString+0x253>
mov    -0x8(%rbp),%rax
mov    (%rax),%rdi
mov    -0x8(%rbp),%rax
mov    (%rax),%rax
add    -0x10(%rax),%rdi
mov    -0x40(%rbp),%rdx
mov    -0x8(%rbp),%rax
mov    (%rax),%rax
sub    -0x10(%rax),%rdx
shl    $0x0,%rdx
xor    %esi,%esi
call   1030 <memset@plt>
mov    -0x40(%rbp),%rcx
mov    -0x8(%rbp),%rax
mov    (%rax),%rax
mov    %rcx,-0x10(%rax)
jmp    13a7 <_ProtoBufString+0x267>
jmp    13ac <_ProtoBufString+0x26c>
mov    -0x38(%rbp),%rax
cmp    -0x28(%rbp),%rax
jae    13ee <_ProtoBufString+0x2ae>
mov    -0x10(%rbp),%rax
mov    -0x38(%rbp),%rcx
mov    %rcx,%rdx
add    $0x1,%rdx
mov    %rdx,-0x38(%rbp)
mov    (%rax,%rcx,1),%dl
mov    -0x8(%rbp),%rax
mov    (%rax),%rax
mov    -0x30(%rbp),%rcx
mov    %rcx,%rsi
add    $0x1,%rsi
mov    %rsi,-0x30(%rbp)
mov    %dl,(%rax,%rcx,1)
jmp    13ac <_ProtoBufString+0x26c>
mov    -0x28(%rbp),%rcx
mov    -0x8(%rbp),%rax
mov    (%rax),%rax
add    -0x8(%rax),%rcx
mov    %rcx,-0x8(%rax)
jmp    1406 <_ProtoBufString+0x2c6>
mov    -0x8(%rbp),%rax
cmpq   $0x0,(%rax)
setne  %al
and    $0x1,%al
movzbl %al,%edi
call   1050 <assert@plt>
mov    -0x8(%rbp),%rax
mov    (%rax),%rax
mov    -0x8(%rax),%rax
add    $0x1,%rax
mov    -0x8(%rbp),%rcx
mov    (%rcx),%rcx
cmp    -0x10(%rcx),%rax
jbe    1520 <_ProtoBufString+0x3e0>
jmp    1440 <_ProtoBufString+0x300>
mov    -0x8(%rbp),%rax
mov    (%rax),%rax
mov    -0x10(%rax),%rax
add    $0x1,%rax
imul   $0x3,%rax,%rax
shr    $0x1,%rax
mov    %rax,-0x48(%rbp)
mov    -0x8(%rbp),%rax
cmpq   $0x0,(%rax)
setne  %al
and    $0x1,%al
movzbl %al,%edi
call   1050 <assert@plt>
mov    -0x48(%rbp),%rax
mov    -0x8(%rbp),%rcx
mov    (%rcx),%rcx
cmp    -0x8(%rcx),%rax
setae  %al
and    $0x1,%al
movzbl %al,%edi
call   1050 <assert@plt>
mov    -0x8(%rbp),%rax
mov    (%rax),%rdi
add    $0xfffffffffffffff0,%rdi
mov    -0x48(%rbp),%rsi
shl    $0x0,%rsi
add    $0x10,%rsi
call   1060 <realloc@plt>
mov    %rax,%rcx
add    $0x10,%rcx
mov    -0x8(%rbp),%rax
mov    %rcx,(%rax)
mov    -0x8(%rbp),%rax
cmpq   $0x0,(%rax)
setne  %al
and    $0x1,%al
movzbl %al,%edi
call   1050 <assert@plt>
mov    -0x48(%rbp),%rax
mov    -0x8(%rbp),%rcx
mov    (%rcx),%rcx
cmp    -0x10(%rcx),%rax
jbe    150c <_ProtoBufString+0x3cc>
mov    -0x8(%rbp),%rax
mov    (%rax),%rdi
mov    -0x8(%rbp),%rax
mov    (%rax),%rax
add    -0x10(%rax),%rdi
mov    -0x48(%rbp),%rdx
mov    -0x8(%rbp),%rax
mov    (%rax),%rax
sub    -0x10(%rax),%rdx
shl    $0x0,%rdx
xor    %esi,%esi
call   1030 <memset@plt>
mov    -0x48(%rbp),%rcx
mov    -0x8(%rbp),%rax
mov    (%rax),%rax
mov    %rcx,-0x10(%rax)
jmp    1520 <_ProtoBufString+0x3e0>
mov    -0x8(%rbp),%rax
mov    (%rax),%rax
mov    -0x8(%rbp),%rcx
mov    (%rcx),%rdx
mov    -0x8(%rdx),%rcx
mov    %rcx,%rsi
add    $0x1,%rsi
mov    %rsi,-0x8(%rdx)
movb   $0x0,(%rax,%rcx,1)
jmp    1546 <_ProtoBufString+0x406>
add    $0x50,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<_ProtoBufString>:
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
mov    %rdx,%r14
mov    %rsi,%r12
mov    %rdi,%r15
test   %rsi,%rsi
jne    1160 <_ProtoBufString+0x20>
test   %r14,%r14
jne    13b9 <_ProtoBufString+0x279>
cmpq   $0x0,(%r15)
jne    11a2 <_ProtoBufString+0x62>
lea    0x1(%r14),%rbx
mov    $0x1,%edi
call   1050 <assert@plt>
lea    0x11(%r14),%rsi
mov    $0x1,%edi
call   1040 <calloc@plt>
add    $0x10,%rax
mov    %rax,(%r15)
mov    $0x1,%edi
call   1050 <assert@plt>
mov    (%r15),%rax
mov    %rbx,-0x10(%rax)
movq   $0x0,-0x8(%rax)
mov    $0x1,%edi
call   1050 <assert@plt>
mov    (%r15),%rdi
mov    -0x8(%rdi),%rdx
xor    %esi,%esi
call   1030 <memset@plt>
mov    (%r15),%rax
movq   $0x0,-0x8(%rax)
xor    %edi,%edi
test   %rax,%rax
setne  %dil
call   1050 <assert@plt>
mov    (%r15),%rax
mov    -0x8(%rax),%rbx
mov    $0x1,%edi
call   1050 <assert@plt>
mov    $0x1,%edi
call   1050 <assert@plt>
lea    (%rbx,%r14,1),%rax
mov    (%r15),%rdi
cmp    -0x10(%rdi),%rax
jbe    125f <_ProtoBufString+0x11f>
lea    (%rax,%rax,2),%r13
shr    %r13
mov    $0x1,%edi
call   1050 <assert@plt>
mov    (%r15),%rax
xor    %edi,%edi
cmp    -0x8(%rax),%r13
setae  %dil
call   1050 <assert@plt>
mov    (%r15),%rdi
add    $0xfffffffffffffff0,%rdi
lea    0x10(%r13),%rsi
call   1060 <realloc@plt>
add    $0x10,%rax
mov    %rax,(%r15)
mov    $0x1,%edi
call   1050 <assert@plt>
mov    (%r15),%rdi
mov    -0x10(%rdi),%rax
mov    %r13,%rdx
sub    %rax,%rdx
jbe    125b <_ProtoBufString+0x11b>
add    %rax,%rdi
xor    %esi,%esi
call   1030 <memset@plt>
mov    (%r15),%rdi
mov    %r13,-0x10(%rdi)
test   %r14,%r14
je     131a <_ProtoBufString+0x1da>
mov    (%r12),%al
mov    %al,(%rdi,%rbx,1)
cmp    $0x1,%r14
je     1317 <_ProtoBufString+0x1d7>
lea    -0x1(%r14),%rdx
lea    -0x2(%r14),%rsi
mov    %edx,%edi
and    $0x3,%edi
mov    $0x1,%ecx
cmp    $0x3,%rsi
jb     12f0 <_ProtoBufString+0x1b0>
and    $0xfffffffffffffffc,%rdx
xor    %ecx,%ecx
nopw   0x0(%rax,%rax,1)
movzbl 0x1(%r12,%rcx,1),%eax
mov    (%r15),%rsi
add    %rbx,%rsi
mov    %al,0x1(%rcx,%rsi,1)
movzbl 0x2(%r12,%rcx,1),%eax
mov    (%r15),%rsi
add    %rbx,%rsi
mov    %al,0x2(%rcx,%rsi,1)
movzbl 0x3(%r12,%rcx,1),%eax
mov    (%r15),%rsi
add    %rbx,%rsi
mov    %al,0x3(%rcx,%rsi,1)
movzbl 0x4(%r12,%rcx,1),%eax
mov    (%r15),%rsi
add    %rbx,%rsi
mov    %al,0x4(%rcx,%rsi,1)
add    $0x4,%rcx
cmp    %rcx,%rdx
jne    12a0 <_ProtoBufString+0x160>
add    %rcx,%rbx
add    $0x1,%rcx
test   %rdi,%rdi
je     1317 <_ProtoBufString+0x1d7>
add    %rcx,%r12
add    $0x1,%rbx
xor    %ecx,%ecx
xchg   %ax,%ax
movzbl (%r12,%rcx,1),%eax
mov    (%r15),%rdx
add    %rbx,%rdx
mov    %al,(%rcx,%rdx,1)
add    $0x1,%rcx
cmp    %rcx,%rdi
jne    1300 <_ProtoBufString+0x1c0>
mov    (%r15),%rdi
add    %r14,-0x8(%rdi)
xor    %eax,%eax
test   %rdi,%rdi
setne  %al
mov    %eax,%edi
call   1050 <assert@plt>
mov    (%r15),%rdi
mov    -0x10(%rdi),%rdx
mov    -0x8(%rdi),%rax
lea    0x1(%rax),%rcx
cmp    %rdx,%rcx
jbe    13b1 <_ProtoBufString+0x271>
lea    (%rdx,%rdx,2),%rbx
add    $0x3,%rbx
shr    %rbx
mov    $0x1,%edi
call   1050 <assert@plt>
mov    (%r15),%rax
xor    %edi,%edi
cmp    -0x8(%rax),%rbx
setae  %dil
call   1050 <assert@plt>
mov    (%r15),%rdi
add    $0xfffffffffffffff0,%rdi
lea    0x10(%rbx),%rsi
call   1060 <realloc@plt>
add    $0x10,%rax
mov    %rax,(%r15)
mov    $0x1,%edi
call   1050 <assert@plt>
mov    (%r15),%rdi
mov    -0x10(%rdi),%rax
mov    %rbx,%rdx
sub    %rax,%rdx
jbe    13a5 <_ProtoBufString+0x265>
add    %rax,%rdi
xor    %esi,%esi
call   1030 <memset@plt>
mov    (%r15),%rdi
mov    %rbx,-0x10(%rdi)
mov    -0x8(%rdi),%rax
lea    0x1(%rax),%rcx
mov    %rcx,-0x8(%rdi)
movb   $0x0,(%rdi,%rax,1)
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
ret

LLVM IR (-O0):
define void @_ProtoBufString(i8** %0, i8* %1, i64 %2) {
%4 = alloca i8**
%5 = alloca i8*
%6 = alloca i64
%7 = alloca i64
%8 = alloca i64
%9 = alloca i64
%10 = alloca i64
%11 = alloca i64
%12 = alloca i64
store i8** %0, i8*** %4
store i8* %1, i8** %5
store i64 %2, i64* %6
%13 = load i8*, i8** %5
%14 = icmp ne i8* %13, null
br i1 %14, label %18, label %15
15: ; preds = %3
%16 = load i64, i64* %6
%17 = icmp eq i64 %16, 0
br i1 %17, label %18, label %305
18: ; preds = %15, %3
%19 = load i8**, i8*** %4
%20 = load i8*, i8** %19
%21 = icmp ne i8* %20, null
br i1 %21, label %53, label %22
22: ; preds = %18
br label %23
23: ; preds = %22
%24 = load i64, i64* %6
%25 = add i64 %24, 1
store i64 %25, i64* %7
%26 = load i64, i64* %7
%27 = icmp uge i64 %26, 0
%28 = zext i1 %27 to i32
%29 = call i32 @assert(i32 %28)
%30 = load i64, i64* %7
%31 = mul i64 %30, 1
%32 = add i64 %31, 16
%33 = call i64 @calloc(i32 1, i64 %32)
%34 = inttoptr i64 %33 to i64*
%35 = getelementptr inbounds i64, i64* %34, i64 2
%36 = bitcast i64* %35 to i8*
%37 = load i8**, i8*** %4
store i8* %36, i8** %37
%38 = load i8**, i8*** %4
%39 = load i8*, i8** %38
%40 = icmp ne i8* %39, null
%41 = zext i1 %40 to i32
%42 = call i32 @assert(i32 %41)
%43 = load i64, i64* %7
%44 = load i8**, i8*** %4
%45 = load i8*, i8** %44
%46 = bitcast i8* %45 to i64*
%47 = getelementptr inbounds i64, i64* %46, i64 -2
store i64 %43, i64* %47
%48 = load i8**, i8*** %4
%49 = load i8*, i8** %48
%50 = bitcast i8* %49 to i64*
%51 = getelementptr inbounds i64, i64* %50, i64 -1
store i64 0, i64* %51
br label %52
52: ; preds = %23
br label %53
53: ; preds = %52, %18
br label %54
54: ; preds = %53
%55 = load i8**, i8*** %4
%56 = load i8*, i8** %55
%57 = icmp ne i8* %56, null
%58 = zext i1 %57 to i32
%59 = call i32 @assert(i32 %58)
%60 = load i8**, i8*** %4
%61 = load i8*, i8** %60
%62 = load i8**, i8*** %4
%63 = load i8*, i8** %62
%64 = bitcast i8* %63 to i64*
%65 = getelementptr inbounds i64, i64* %64, i64 -1
%66 = load i64, i64* %65
%67 = mul i64 %66, 1
%68 = call i32 @memset(i8* %61, i32 0, i64 %67)
%69 = load i8**, i8*** %4
%70 = load i8*, i8** %69
%71 = bitcast i8* %70 to i64*
%72 = getelementptr inbounds i64, i64* %71, i64 -1
store i64 0, i64* %72
br label %73
73: ; preds = %54
br label %74
74: ; preds = %73
%75 = load i8**, i8*** %4
%76 = load i8*, i8** %75
%77 = icmp ne i8* %76, null
%78 = zext i1 %77 to i32
%79 = call i32 @assert(i32 %78)
%80 = load i64, i64* %6
store i64 %80, i64* %8
%81 = load i8**, i8*** %4
%82 = load i8*, i8** %81
%83 = bitcast i8* %82 to i64*
%84 = getelementptr inbounds i64, i64* %83, i64 -1
%85 = load i64, i64* %84
store i64 %85, i64* %9
store i64 0, i64* %10
%86 = load i8*, i8** %5
%87 = icmp ne i8* %86, null
br i1 %87, label %91, label %88
88: ; preds = %74
%89 = load i64, i64* %8
%90 = icmp eq i64 %89, 0
br label %91
91: ; preds = %88, %74
%92 = phi i1 [ true, %74 ], [ %90, %88 ]
%93 = zext i1 %92 to i32
%94 = call i32 @assert(i32 %93)
%95 = load i64, i64* %8
%96 = icmp uge i64 %95, 0
%97 = zext i1 %96 to i32
%98 = call i32 @assert(i32 %97)
%99 = load i64, i64* %9
%100 = load i64, i64* %8
%101 = add i64 %99, %100
%102 = load i8**, i8*** %4
%103 = load i8*, i8** %102
%104 = bitcast i8* %103 to i64*
%105 = getelementptr inbounds i64, i64* %104, i64 -2
%106 = load i64, i64* %105
%107 = icmp ugt i64 %101, %106
br i1 %107, label %108, label %178
108: ; preds = %91
br label %109
109: ; preds = %108
%110 = load i64, i64* %9
%111 = load i64, i64* %8
%112 = add i64 %110, %111
%113 = mul i64 %112, 3
%114 = udiv i64 %113, 2
store i64 %114, i64* %11
%115 = load i8**, i8*** %4
%116 = load i8*, i8** %115
%117 = icmp ne i8* %116, null
%118 = zext i1 %117 to i32
%119 = call i32 @assert(i32 %118)
%120 = load i64, i64* %11
%121 = load i8**, i8*** %4
%122 = load i8*, i8** %121
%123 = bitcast i8* %122 to i64*
%124 = getelementptr inbounds i64, i64* %123, i64 -1
%125 = load i64, i64* %124
%126 = icmp uge i64 %120, %125
%127 = zext i1 %126 to i32
%128 = call i32 @assert(i32 %127)
%129 = load i8**, i8*** %4
%130 = load i8*, i8** %129
%131 = bitcast i8* %130 to i64*
%132 = getelementptr inbounds i64, i64* %131, i64 -2
%133 = load i64, i64* %11
%134 = mul i64 %133, 1
%135 = add i64 %134, 16
%136 = call i64 @realloc(i64* %132, i64 %135)
%137 = inttoptr i64 %136 to i64*
%138 = getelementptr inbounds i64, i64* %137, i64 2
%139 = bitcast i64* %138 to i8*
%140 = load i8**, i8*** %4
store i8* %139, i8** %140
%141 = load i8**, i8*** %4
%142 = load i8*, i8** %141
%143 = icmp ne i8* %142, null
%144 = zext i1 %143 to i32
%145 = call i32 @assert(i32 %144)
%146 = load i64, i64* %11
%147 = load i8**, i8*** %4
%148 = load i8*, i8** %147
%149 = bitcast i8* %148 to i64*
%150 = getelementptr inbounds i64, i64* %149, i64 -2
%151 = load i64, i64* %150
%152 = icmp ugt i64 %146, %151
br i1 %152, label %153, label %171
153: ; preds = %109
%154 = load i8**, i8*** %4
%155 = load i8*, i8** %154
%156 = load i8**, i8*** %4
%157 = load i8*, i8** %156
%158 = bitcast i8* %157 to i64*
%159 = getelementptr inbounds i64, i64* %158, i64 -2
%160 = load i64, i64* %159
%161 = getelementptr inbounds i8, i8* %155, i64 %160
%162 = load i64, i64* %11
%163 = load i8**, i8*** %4
%164 = load i8*, i8** %163
%165 = bitcast i8* %164 to i64*
%166 = getelementptr inbounds i64, i64* %165, i64 -2
%167 = load i64, i64* %166
%168 = sub i64 %162, %167
%169 = mul i64 %168, 1
%170 = call i32 @memset(i8* %161, i32 0, i64 %169)
br label %171
171: ; preds = %153, %109
%172 = load i64, i64* %11
%173 = load i8**, i8*** %4
%174 = load i8*, i8** %173
%175 = bitcast i8* %174 to i64*
%176 = getelementptr inbounds i64, i64* %175, i64 -2
store i64 %172, i64* %176
br label %177
177: ; preds = %171
br label %178
178: ; preds = %177, %91
br label %179
179: ; preds = %183, %178
%180 = load i64, i64* %10
%181 = load i64, i64* %8
%182 = icmp ult i64 %180, %181
br i1 %182, label %183, label %194
183: ; preds = %179
%184 = load i8*, i8** %5
%185 = load i64, i64* %10
%186 = add i64 %185, 1
store i64 %186, i64* %10
%187 = getelementptr inbounds i8, i8* %184, i64 %185
%188 = load i8, i8* %187
%189 = load i8**, i8*** %4
%190 = load i8*, i8** %189
%191 = load i64, i64* %9
%192 = add i64 %191, 1
store i64 %192, i64* %9
%193 = getelementptr inbounds i8, i8* %190, i64 %191
store i8 %188, i8* %193
br label %179
194: ; preds = %179
%195 = load i64, i64* %8
%196 = load i8**, i8*** %4
%197 = load i8*, i8** %196
%198 = bitcast i8* %197 to i64*
%199 = getelementptr inbounds i64, i64* %198, i64 -1
%200 = load i64, i64* %199
%201 = add i64 %200, %195
store i64 %201, i64* %199
br label %202
202: ; preds = %194
br label %203
203: ; preds = %202
%204 = load i8**, i8*** %4
%205 = load i8*, i8** %204
%206 = icmp ne i8* %205, null
%207 = zext i1 %206 to i32
%208 = call i32 @assert(i32 %207)
%209 = load i8**, i8*** %4
%210 = load i8*, i8** %209
%211 = bitcast i8* %210 to i64*
%212 = getelementptr inbounds i64, i64* %211, i64 -1
%213 = load i64, i64* %212
%214 = add i64 %213, 1
%215 = load i8**, i8*** %4
%216 = load i8*, i8** %215
%217 = bitcast i8* %216 to i64*
%218 = getelementptr inbounds i64, i64* %217, i64 -2
%219 = load i64, i64* %218
%220 = icmp ugt i64 %214, %219
br i1 %220, label %221, label %294
221: ; preds = %203
br label %222
222: ; preds = %221
%223 = load i8**, i8*** %4
%224 = load i8*, i8** %223
%225 = bitcast i8* %224 to i64*
%226 = getelementptr inbounds i64, i64* %225, i64 -2
%227 = load i64, i64* %226
%228 = add i64 %227, 1
%229 = mul i64 %228, 3
%230 = udiv i64 %229, 2
store i64 %230, i64* %12
%231 = load i8**, i8*** %4
%232 = load i8*, i8** %231
%233 = icmp ne i8* %232, null
%234 = zext i1 %233 to i32
%235 = call i32 @assert(i32 %234)
%236 = load i64, i64* %12
%237 = load i8**, i8*** %4
%238 = load i8*, i8** %237
%239 = bitcast i8* %238 to i64*
%240 = getelementptr inbounds i64, i64* %239, i64 -1
%241 = load i64, i64* %240
%242 = icmp uge i64 %236, %241
%243 = zext i1 %242 to i32
%244 = call i32 @assert(i32 %243)
%245 = load i8**, i8*** %4
%246 = load i8*, i8** %245
%247 = bitcast i8* %246 to i64*
%248 = getelementptr inbounds i64, i64* %247, i64 -2
%249 = load i64, i64* %12
%250 = mul i64 %249, 1
%251 = add i64 %250, 16
%252 = call i64 @realloc(i64* %248, i64 %251)
%253 = inttoptr i64 %252 to i64*
%254 = getelementptr inbounds i64, i64* %253, i64 2
%255 = bitcast i64* %254 to i8*
%256 = load i8**, i8*** %4
store i8* %255, i8** %256
%257 = load i8**, i8*** %4
%258 = load i8*, i8** %257
%259 = icmp ne i8* %258, null
%260 = zext i1 %259 to i32
%261 = call i32 @assert(i32 %260)
%262 = load i64, i64* %12
%263 = load i8**, i8*** %4
%264 = load i8*, i8** %263
%265 = bitcast i8* %264 to i64*
%266 = getelementptr inbounds i64, i64* %265, i64 -2
%267 = load i64, i64* %266
%268 = icmp ugt i64 %262, %267
br i1 %268, label %269, label %287
269: ; preds = %222
%270 = load i8**, i8*** %4
%271 = load i8*, i8** %270
%272 = load i8**, i8*** %4
%273 = load i8*, i8** %272
%274 = bitcast i8* %273 to i64*
%275 = getelementptr inbounds i64, i64* %274, i64 -2
%276 = load i64, i64* %275
%277 = getelementptr inbounds i8, i8* %271, i64 %276
%278 = load i64, i64* %12
%279 = load i8**, i8*** %4
%280 = load i8*, i8** %279
%281 = bitcast i8* %280 to i64*
%282 = getelementptr inbounds i64, i64* %281, i64 -2
%283 = load i64, i64* %282
%284 = sub i64 %278, %283
%285 = mul i64 %284, 1
%286 = call i32 @memset(i8* %277, i32 0, i64 %285)
br label %287
287: ; preds = %269, %222
%288 = load i64, i64* %12
%289 = load i8**, i8*** %4
%290 = load i8*, i8** %289
%291 = bitcast i8* %290 to i64*
%292 = getelementptr inbounds i64, i64* %291, i64 -2
store i64 %288, i64* %292
br label %293
293: ; preds = %287
br label %294
294: ; preds = %293, %203
%295 = load i8**, i8*** %4
%296 = load i8*, i8** %295
%297 = load i8**, i8*** %4
%298 = load i8*, i8** %297
%299 = bitcast i8* %298 to i64*
%300 = getelementptr inbounds i64, i64* %299, i64 -1
%301 = load i64, i64* %300
%302 = add i64 %301, 1
store i64 %302, i64* %300
%303 = getelementptr inbounds i8, i8* %296, i64 %301
store i8 0, i8* %303
br label %304
304: ; preds = %294
br label %305
305: ; preds = %304, %15
ret void
}

LLVM IR (-O2):
define void @_ProtoBufString(i8** %0, i8* %1, i64 %2) {
%4 = icmp ne i8* %1, null
%5 = icmp eq i64 %2, 0
%6 = or i1 %4, %5
br i1 %6, label %7, label %203
7: ; preds = %3
%8 = load i8*, i8** %0
%9 = icmp eq i8* %8, null
br i1 %9, label %10, label %22
10: ; preds = %7
%11 = add i64 %2, 1
%12 = tail call i32 @assert(i32 1)
%13 = add i64 %2, 17
%14 = tail call i64 @calloc(i32 1, i64 %13)
%15 = inttoptr i64 %14 to i64*
%16 = getelementptr inbounds i64, i64* %15, i64 2
%17 = bitcast i8** %0 to i64**
store i64* %16, i64** %17
%18 = tail call i32 @assert(i32 1)
%19 = load i64*, i64** %17
%20 = getelementptr inbounds i64, i64* %19, i64 -2
store i64 %11, i64* %20
%21 = getelementptr inbounds i64, i64* %19, i64 -1
store i64 0, i64* %21
br label %22
22: ; preds = %7, %10
%23 = bitcast i8** %0 to i64**
%24 = tail call i32 @assert(i32 1)
%25 = load i8*, i8** %0
%26 = getelementptr inbounds i8, i8* %25, i64 -8
%27 = bitcast i8* %26 to i64*
%28 = load i64, i64* %27
%29 = tail call i32 @memset(i8* %25, i32 0, i64 %28)
%30 = load i64*, i64** %23
%31 = getelementptr inbounds i64, i64* %30, i64 -1
store i64 0, i64* %31
%32 = icmp ne i64* %30, null
%33 = zext i1 %32 to i32
%34 = tail call i32 @assert(i32 %33)
%35 = load i64*, i64** %23
%36 = getelementptr inbounds i64, i64* %35, i64 -1
%37 = load i64, i64* %36
%38 = tail call i32 @assert(i32 1)
%39 = tail call i32 @assert(i32 1)
%40 = add i64 %37, %2
%41 = load i8*, i8** %0
%42 = getelementptr inbounds i8, i8* %41, i64 -16
%43 = bitcast i8* %42 to i64*
%44 = load i64, i64* %43
%45 = icmp ugt i64 %40, %44
%46 = bitcast i8* %41 to i64*
br i1 %45, label %47, label %80
47: ; preds = %22
%48 = mul i64 %40, 3
%49 = lshr i64 %48, 1
%50 = tail call i32 @assert(i32 1)
%51 = load i64*, i64** %23
%52 = getelementptr inbounds i64, i64* %51, i64 -1
%53 = load i64, i64* %52
%54 = icmp uge i64 %49, %53
%55 = zext i1 %54 to i32
%56 = tail call i32 @assert(i32 %55)
%57 = load i64*, i64** %23
%58 = getelementptr inbounds i64, i64* %57, i64 -2
%59 = add nuw i64 %49, 16
%60 = tail call i64 @realloc(i64* %58, i64 %59)
%61 = inttoptr i64 %60 to i64*
%62 = getelementptr inbounds i64, i64* %61, i64 2
store i64* %62, i64** %23
%63 = tail call i32 @assert(i32 1)
%64 = load i8*, i8** %0
%65 = getelementptr inbounds i8, i8* %64, i64 -16
%66 = bitcast i8* %65 to i64*
%67 = load i64, i64* %66
%68 = icmp ugt i64 %49, %67
%69 = bitcast i8* %64 to i64*
br i1 %68, label %70, label %76
70: ; preds = %47
%71 = getelementptr inbounds i8, i8* %64, i64 %67
%72 = sub i64 %49, %67
%73 = tail call i32 @memset(i8* %71, i32 0, i64 %72)
%74 = load i64*, i64** %23
%75 = bitcast i64* %74 to i8*
br label %76
76: ; preds = %70, %47
%77 = phi i64* [ %74, %70 ], [ %69, %47 ]
%78 = phi i8* [ %75, %70 ], [ %64, %47 ]
%79 = getelementptr inbounds i64, i64* %77, i64 -2
store i64 %49, i64* %79
br label %80
80: ; preds = %76, %22
%81 = phi i64* [ %77, %76 ], [ %46, %22 ]
%82 = phi i8* [ %78, %76 ], [ %41, %22 ]
br i1 %5, label %142, label %83
83: ; preds = %80
%84 = load i8, i8* %1
%85 = getelementptr inbounds i8, i8* %82, i64 %37
store i8 %84, i8* %85
%86 = icmp eq i64 %2, 1
br i1 %86, label %140, label %87
87: ; preds = %83
%88 = add i64 %2, -1
%89 = add i64 %2, -2
%90 = and i64 %88, 3
%91 = icmp ult i64 %89, 3
br i1 %91, label %124, label %92
92: ; preds = %87
%93 = and i64 %88, -4
br label %94
94: ; preds = %94, %92
%95 = phi i64 [ 1, %92 ], [ %118, %94 ]
%96 = phi i64 [ %37, %92 ], [ %116, %94 ]
%97 = phi i64 [ 0, %92 ], [ %122, %94 ]
%98 = add i64 %96, 1
%99 = load i8*, i8** %0
%100 = add nuw nsw i64 %95, 1
%101 = getelementptr inbounds i8, i8* %1, i64 %95
%102 = load i8, i8* %101
%103 = getelementptr inbounds i8, i8* %99, i64 %98
store i8 %102, i8* %103
%104 = add i64 %96, 2
%105 = load i8*, i8** %0
%106 = add nuw nsw i64 %95, 2
%107 = getelementptr inbounds i8, i8* %1, i64 %100
%108 = load i8, i8* %107
%109 = getelementptr inbounds i8, i8* %105, i64 %104
store i8 %108, i8* %109
%110 = add i64 %96, 3
%111 = load i8*, i8** %0
%112 = add nuw i64 %95, 3
%113 = getelementptr inbounds i8, i8* %1, i64 %106
%114 = load i8, i8* %113
%115 = getelementptr inbounds i8, i8* %111, i64 %110
store i8 %114, i8* %115
%116 = add i64 %96, 4
%117 = load i8*, i8** %0
%118 = add nuw i64 %95, 4
%119 = getelementptr inbounds i8, i8* %1, i64 %112
%120 = load i8, i8* %119
%121 = getelementptr inbounds i8, i8* %117, i64 %116
store i8 %120, i8* %121
%122 = add i64 %97, 4
%123 = icmp eq i64 %122, %93
br i1 %123, label %124, label %94
124: ; preds = %94, %87
%125 = phi i64 [ 1, %87 ], [ %118, %94 ]
%126 = phi i64 [ %37, %87 ], [ %116, %94 ]
%127 = icmp eq i64 %90, 0
br i1 %127, label %140, label %128
128: ; preds = %124, %128
%129 = phi i64 [ %134, %128 ], [ %125, %124 ]
%130 = phi i64 [ %132, %128 ], [ %126, %124 ]
%131 = phi i64 [ %138, %128 ], [ 0, %124 ]
%132 = add i64 %130, 1
%133 = load i8*, i8** %0
%134 = add nuw i64 %129, 1
%135 = getelementptr inbounds i8, i8* %1, i64 %129
%136 = load i8, i8* %135
%137 = getelementptr inbounds i8, i8* %133, i64 %132
store i8 %136, i8* %137
%138 = add i64 %131, 1
%139 = icmp eq i64 %138, %90
br i1 %139, label %140, label %128
140: ; preds = %124, %128, %83
%141 = load i64*, i64** %23
br label %142
142: ; preds = %140, %80
%143 = phi i64* [ %141, %140 ], [ %81, %80 ]
%144 = getelementptr inbounds i64, i64* %143, i64 -1
%145 = load i64, i64* %144
%146 = add i64 %145, %2
store i64 %146, i64* %144
%147 = icmp ne i64* %143, null
%148 = zext i1 %147 to i32
%149 = tail call i32 @assert(i32 %148)
%150 = load i8*, i8** %0
%151 = getelementptr inbounds i8, i8* %150, i64 -8
%152 = bitcast i8* %151 to i64*
%153 = load i64, i64* %152
%154 = add i64 %153, 1
%155 = getelementptr inbounds i8, i8* %150, i64 -16
%156 = bitcast i8* %155 to i64*
%157 = load i64, i64* %156
%158 = icmp ugt i64 %154, %157
br i1 %158, label %159, label %197
159: ; preds = %142
%160 = mul i64 %157, 3
%161 = add i64 %160, 3
%162 = lshr i64 %161, 1
%163 = tail call i32 @assert(i32 1)
%164 = load i64*, i64** %23
%165 = getelementptr inbounds i64, i64* %164, i64 -1
%166 = load i64, i64* %165
%167 = icmp uge i64 %162, %166
%168 = zext i1 %167 to i32
%169 = tail call i32 @assert(i32 %168)
%170 = load i64*, i64** %23
%171 = getelementptr inbounds i64, i64* %170, i64 -2
%172 = add nuw i64 %162, 16
%173 = tail call i64 @realloc(i64* %171, i64 %172)
%174 = inttoptr i64 %173 to i64*
%175 = getelementptr inbounds i64, i64* %174, i64 2
store i64* %175, i64** %23
%176 = tail call i32 @assert(i32 1)
%177 = load i8*, i8** %0
%178 = getelementptr inbounds i8, i8* %177, i64 -16
%179 = bitcast i8* %178 to i64*
%180 = load i64, i64* %179
%181 = icmp ugt i64 %162, %180
%182 = bitcast i8* %177 to i64*
br i1 %181, label %183, label %189
183: ; preds = %159
%184 = getelementptr inbounds i8, i8* %177, i64 %180
%185 = sub i64 %162, %180
%186 = tail call i32 @memset(i8* %184, i32 0, i64 %185)
%187 = load i64*, i64** %23
%188 = bitcast i64* %187 to i8*
br label %189
189: ; preds = %183, %159
%190 = phi i8* [ %188, %183 ], [ %177, %159 ]
%191 = phi i64* [ %187, %183 ], [ %182, %159 ]
%192 = getelementptr inbounds i64, i64* %191, i64 -2
store i64 %162, i64* %192
%193 = getelementptr inbounds i8, i8* %190, i64 -8
%194 = bitcast i8* %193 to i64*
%195 = load i64, i64* %194
%196 = add i64 %195, 1
br label %197
197: ; preds = %189, %142
%198 = phi i64 [ %196, %189 ], [ %154, %142 ]
%199 = phi i64* [ %194, %189 ], [ %152, %142 ]
%200 = phi i64 [ %195, %189 ], [ %153, %142 ]
%201 = phi i8* [ %190, %189 ], [ %150, %142 ]
store i64 %198, i64* %199
%202 = getelementptr inbounds i8, i8* %201, i64 %200
store i8 0, i8* %202
br label %203
203: ; preds = %3, %197
ret void
}