// File: /workspace/github_cpp_makefile_star2_O1/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 0x39da(%rip), %rsi      # 0x6004
callq 0x21f0
testq %rax, %rax
je 0x272a
movq %rax, %r15
movq %rax, %rdi
xorl %esi, %esi
movl $0x2, %edx
callq 0x21c0
testl %eax, %eax
jne 0x2734
movq %r15, %rdi
callq 0x2030
cmpq $-0x1, %rax
je 0x2741
movq %rax, %r12
movq %r15, %rdi
callq 0x2060
movq %r12, %rdi
callq 0x2200
movq %rax, %r13
movl $0x1, %esi
movq %rax, %rdi
movq %r12, %rdx
movq %r15, %rcx
callq 0x2250
movq %rax, %rbp
movq %r15, %rdi
callq 0x2190
cmpq %r12, %rbp
jne 0x274b
movl $0x100000, %edi         # imm = 0x100000
movl $0x1, %esi
callq 0x2120
movq %rax, %r14
testq %rax, %rax
je 0x276b
leaq 0x18(%rsp), %rbp
movq %rbp, -0x10(%rbp)
movq %r13, %rdx
addq %r12, %rdx
leaq 0x8(%rsp), %r15
movq %r15, %rdi
movq %r13, %rsi
callq 0x2d6e
movq (%r15), %rsi
movq 0x8(%r15), %rdx
addq %rsi, %rdx
movq (%rbx), %rax
movq %rbx, %rdi
callq *(%rax)
movl $0x1, %r15d
testb %al, %al
je 0x2719
movq (%rbx), %rax
xorl %r15d, %r15d
leaq 0x8b(%rip), %rsi        # 0x278f
leaq 0x94(%rip), %rcx        # 0x279f
movq %rbx, %rdi
xorl %edx, %edx
xorl %r8d, %r8d
movq %r14, %r9
callq *0x8(%rax)
movq 0x8(%rsp), %rdi
cmpq %rbp, %rdi
je 0x2759
callq 0x2180
jmp 0x2759
movq %r14, %rdi
callq 0x23d1
jmp 0x2753
movq %r14, %rdi
movq %r15, %rsi
callq 0x2300
jmp 0x2753
movq %r14, %rdi
callq 0x2396
jmp 0x2753
movq %r14, %rdi
callq 0x233e
movl $0x1, %r15d
movl %r15d, %eax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
callq 0x2379
jmp 0x26bc
movq %rax, %rbx
movq 0x8(%rsp), %rdi
cmpq %rbp, %rdi
je 0x2787
callq 0x2180
movq %rbx, %rdi
callq 0x22a0