// File: /workspace/github_cpp_makefile_star2_O2/brianquinlan[P]brainfuck-jit/bf_main.cpp
// Function: run_brainfuck_program(BrainfuckRunner*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&)
int run_brainfuck_program(BrainfuckRunner* runner,
                          const string& source_file_path) {
  FILE *bf_source_file = fopen(source_file_path.c_str(), "rb");
  if (bf_source_file == NULL) {
    fprintf(stderr, "Could not open file \"%s\": %s\n",
            source_file_path.c_str(), strerror(errno));
    return 1;
  }

  if (fseek(bf_source_file, 0, SEEK_END)) {
    fprintf(stderr, "Could not seek in \"%s\": %s\n",
            source_file_path.c_str(), strerror(ferror(bf_source_file)));
    return 1;
  }

  long source_size = ftell(bf_source_file);
  if (source_size == -1) {
    fprintf(stderr, "Could not tell in \"%s\": %s\n",
            source_file_path.c_str(), strerror(errno));
    return 1;
  }
  rewind(bf_source_file);

  char* source_buffer = reinterpret_cast<char *>(malloc(source_size));
  size_t amount_read = fread(source_buffer, 1, source_size, bf_source_file);
  fclose(bf_source_file);
  if (amount_read != static_cast<size_t>(source_size)) {
    fprintf(stderr, "Error reading file \"%s\": %s\n",
            source_file_path.c_str(), strerror(errno));
    return 1;
  }

  void* memory = calloc(kBrainfuckMemorySize, 1);
  if (memory == NULL) {
    fprintf(stderr,
            "Unable to allocate memory %ld bytes for Brainfuck memory\n",
            static_cast<unsigned long>(kBrainfuckMemorySize));
  }

  const string source(source_buffer, source_size);

  if (!runner->init(source.begin(), source.end())) {
    return 1;
  }

  runner->run(bf_read, NULL, bf_write, NULL, memory);
  return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movq %rsi, %r14
movq %rdi, %rbx
movq (%rsi), %rdi
leaq 0x2bca(%rip), %rsi      # 0x5004
callq 0x21f0
testq %rax, %rax
je 0x2532
movq %rax, %r12
pushq $0x2
popq %rdx
movq %rax, %rdi
xorl %esi, %esi
callq 0x21d0
testl %eax, %eax
jne 0x2554
movq %r12, %rdi
callq 0x2030
cmpq $-0x1, %rax
je 0x2579
movq %rax, %r15
movq %r12, %rdi
callq 0x2060
movq %r15, %rdi
callq 0x2210
movq %rax, %r13
pushq $0x1
popq %rsi
movq %rax, %rdi
movq %r15, %rdx
movq %r12, %rcx
callq 0x2270
movq %rax, %rbp
movq %r12, %rdi
callq 0x21a0
cmpq %r15, %rbp
jne 0x259b
pushq $0x1
popq %rsi
movl $0x100000, %edi         # imm = 0x100000
callq 0x2130
movq %rax, %r14
testq %rax, %rax
je 0x25e1
leaq 0x18(%rsp), %rax
movq %rax, -0x10(%rax)
movq %r13, %rdx
addq %r15, %rdx
leaq 0x8(%rsp), %r15
movq %r15, %rdi
movq %r13, %rsi
callq 0x2afe
movq (%r15), %rsi
movq 0x8(%r15), %rdx
addq %rsi, %rdx
movq (%rbx), %rax
movq %rbx, %rdi
callq *(%rax)
testb %al, %al
je 0x251f
movq (%rbx), %rax
xorl %r15d, %r15d
leaq 0x110(%rip), %rsi       # 0x2618
leaq 0x119(%rip), %rcx       # 0x2628
movq %rbx, %rdi
xorl %edx, %edx
xorl %r8d, %r8d
movq %r14, %r9
callq *0x8(%rax)
jmp 0x2523
pushq $0x1
popq %r15
leaq 0x8(%rsp), %rdi
callq 0x20f0
jmp 0x25cf
movq 0x6aa7(%rip), %rax      # 0x8fe0
movq (%rax), %rbx
movq (%r14), %r14
callq 0x2040
movl (%rax), %edi
callq 0x20a0
leaq 0x2ab5(%rip), %rsi      # 0x5007
jmp 0x25bb
movq 0x6a85(%rip), %rax      # 0x8fe0
movq (%rax), %rbx
movq (%r14), %r14
movq %r12, %rdi
callq 0x22e0
movl %eax, %edi
callq 0x20a0
leaq 0x2aae(%rip), %rsi      # 0x5025
jmp 0x25bb
movq 0x6a60(%rip), %rax      # 0x8fe0
movq (%rax), %rbx
movq (%r14), %r14
callq 0x2040
movl (%rax), %edi
callq 0x20a0
leaq 0x2aa8(%rip), %rsi      # 0x5041
jmp 0x25bb
movq 0x6a3e(%rip), %rax      # 0x8fe0
movq (%rax), %rbx
movq (%r14), %r14
callq 0x2040
movl (%rax), %edi
callq 0x20a0
leaq 0x2aa2(%rip), %rsi      # 0x505d
movq %rbx, %rdi
movq %r14, %rdx
movq %rax, %rcx
xorl %eax, %eax
callq 0x2250
pushq $0x1
popq %r15
movl %r15d, %eax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x69f8(%rip), %rax      # 0x8fe0
movq (%rax), %rdi
leaq 0x2a88(%rip), %rsi      # 0x507a
movl $0x100000, %edx         # imm = 0x100000
xorl %eax, %eax
callq 0x2250
jmp 0x24c6
movq %rax, %rbx
leaq 0x8(%rsp), %rdi
callq 0x20f0
movq %rbx, %rdi
callq 0x22b0