// File: /workspace/github_c_makefile_star2_O1/deplinenoise[P]tundra/src/Driver.cpp
// Function: t2::DriverSaveBuildState(t2::Driver*)
bool DriverSaveBuildState(Driver* self)
{
  TimingScope timing_scope(nullptr, &g_Stats.m_StateSaveTimeCycles);
  ProfilerScope prof_scope("Tundra SaveState", 0);

  MemAllocLinearScope alloc_scope(&self->m_Allocator);

  BinaryWriter writer;
  BinaryWriterInit(&writer, &self->m_Heap);

  BinarySegment *main_seg   = BinaryWriterAddSegment(&writer);
  BinarySegment *guid_seg   = BinaryWriterAddSegment(&writer);
  BinarySegment *state_seg  = BinaryWriterAddSegment(&writer);
  BinarySegment *array_seg  = BinaryWriterAddSegment(&writer);
  BinarySegment *string_seg = BinaryWriterAddSegment(&writer);

  BinaryLocator guid_ptr  = BinarySegmentPosition(guid_seg);
  BinaryLocator state_ptr = BinarySegmentPosition(state_seg);

  uint32_t             src_count       = self->m_DagData->m_NodeCount;
  const HashDigest    *src_guids       = self->m_DagData->m_NodeGuids;
  const NodeData      *src_data        = self->m_DagData->m_NodeData;
  NodeState           *new_state       = self->m_Nodes.m_Storage;
  const size_t         new_state_count = self->m_Nodes.m_Size;

  std::sort(new_state, new_state + new_state_count, [=](const NodeState& l, const NodeState& r) {
    // We know guids are sorted, so all we need to do is compare pointers into that table.
    return l.m_MmapData < r.m_MmapData;
  });

  const HashDigest    *old_guids       = nullptr;
  const NodeStateData *old_state       = nullptr;
  uint32_t             old_count       = 0;

  if (const StateData* state_data = self->m_StateData)
  {
    old_guids      = state_data->m_NodeGuids;
    old_state      = state_data->m_NodeStates;
    old_count      = state_data->m_NodeCount;
  }

  int entry_count = 0;

  auto save_node_state = [=](int build_result, const HashDigest* input_signature, const NodeData* src_node, const HashDigest* guid) -> void
  {
    BinarySegmentWrite(guid_seg, (const char*) guid, sizeof(HashDigest));

    BinarySegmentWriteInt32(state_seg, build_result);
    BinarySegmentWrite(state_seg, (const char*) input_signature, sizeof(HashDigest));

    int32_t file_count = src_node->m_OutputFiles.GetCount();
    BinarySegmentWriteInt32(state_seg, file_count);
    BinarySegmentWritePointer(state_seg, BinarySegmentPosition(array_seg));
    for (int32_t i = 0; i < file_count; ++i)
    {
      BinarySegmentWritePointer(array_seg, BinarySegmentPosition(string_seg));
      BinarySegmentWriteStringData(string_seg, src_node->m_OutputFiles[i].m_Filename);
    }

    file_count = src_node->m_AuxOutputFiles.GetCount();
    BinarySegmentWriteInt32(state_seg, file_count);
    BinarySegmentWritePointer(state_seg, BinarySegmentPosition(array_seg));
    for (int32_t i = 0; i < file_count; ++i)
    {
      BinarySegmentWritePointer(array_seg, BinarySegmentPosition(string_seg));
      BinarySegmentWriteStringData(string_seg, src_node->m_AuxOutputFiles[i].m_Filename);
    }
  };

  auto save_node_state_old = [=](int build_result, const HashDigest* input_signature, const NodeStateData* src_node, const HashDigest* guid) -> void
  {
    BinarySegmentWrite(guid_seg, (const char*) guid, sizeof(HashDigest));

    BinarySegmentWriteInt32(state_seg, build_result);
    BinarySegmentWrite(state_seg, (const char*) input_signature, sizeof(HashDigest));

    int32_t file_count = src_node->m_OutputFiles.GetCount();
    BinarySegmentWriteInt32(state_seg, file_count);
    BinarySegmentWritePointer(state_seg, BinarySegmentPosition(array_seg));
    for (int32_t i = 0; i < file_count; ++i)
    {
      BinarySegmentWritePointer(array_seg, BinarySegmentPosition(string_seg));
      BinarySegmentWriteStringData(string_seg, src_node->m_OutputFiles[i]);
    }

    file_count = src_node->m_AuxOutputFiles.GetCount();
    BinarySegmentWriteInt32(state_seg, file_count);
    BinarySegmentWritePointer(state_seg, BinarySegmentPosition(array_seg));
    for (int32_t i = 0; i < file_count; ++i)
    {
      BinarySegmentWritePointer(array_seg, BinarySegmentPosition(string_seg));
      BinarySegmentWriteStringData(string_seg, src_node->m_AuxOutputFiles[i]);
    }
  };

  auto save_new = [=, &entry_count](size_t index) {
    const NodeState  *elem      = new_state + index;
    const NodeData   *src_elem  = elem->m_MmapData;
    const int         src_index = int(src_elem - src_data);
    const HashDigest *guid      = src_guids + src_index;

    // If this node never computed an input signature (due to an error, or build cancellation), copy the old build progress over to retain the history.
    // Only do this if the output files and aux output files agree with the previously stored build state.
    if (elem->m_Progress < BuildProgress::kUnblocked)
    {
      if (const HashDigest* old_guid = BinarySearch(old_guids, old_count, *guid))
      {
        size_t old_index = old_guid - old_guids;
        const NodeStateData* old_state_data = old_state + old_index;
        save_node_state_old(old_state_data->m_BuildResult, &old_state_data->m_InputSignature, old_state_data, guid);
        ++entry_count;
        ++g_Stats.m_StateSaveNew;
      }
    }
    else
    {
      save_node_state(elem->m_BuildResult, &elem->m_InputSignature, src_elem, guid);
      ++entry_count;
      ++g_Stats.m_StateSaveNew;
    }
  };

  auto save_old = [=, &entry_count](size_t index) {
    const HashDigest    *guid = old_guids + index;

    // Make sure this node is still relevant before saving.
    if (const HashDigest* new_version = BinarySearch(src_guids, src_count, *guid))
    {
      size_t src_index = (new_version - src_guids);
      const NodeData* src_elem = src_data + src_index;
      const NodeStateData *data = old_state + index;

      save_node_state(data->m_BuildResult, &data->m_InputSignature, src_elem, guid);
      ++entry_count;
      ++g_Stats.m_StateSaveOld;
    }
    else
    {
      // Drop this node.
      ++g_Stats.m_StateSaveDropped;
    }
  };

  auto key_new = [=](size_t index) -> const HashDigest* {
    int dag_index = int(new_state[index].m_MmapData - src_data);
    return src_guids + dag_index;
  };

  auto key_old = [=](size_t index) {
    return old_guids + index;
  };

  TraverseSortedArrays(
      new_state_count, save_new, key_new,
      old_count, save_old, key_old);

  // Complete main data structure.
  BinarySegmentWriteUint32(main_seg, StateData::MagicNumber);
  BinarySegmentWriteInt32(main_seg, entry_count);
  BinarySegmentWritePointer(main_seg, guid_ptr);
  BinarySegmentWritePointer(main_seg, state_ptr);

  // Unmap old state data.
  MmapFileUnmap(&self->m_StateFile);
  self->m_StateData = nullptr;

  bool success = BinaryWriterFlush(&writer, self->m_DagData->m_StateFileNameTmp);

  if (success)
  {
    // Commit atomically with a file rename.
    success = RenameFile(self->m_DagData->m_StateFileNameTmp, self->m_DagData->m_StateFileName);
  }
  else
  {
    remove(self->m_DagData->m_StateFileNameTmp);
  }

  BinaryWriterDestroy(&writer);

  return success;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x178, %rsp            # imm = 0x178
movq %rdi, 0x8(%rsp)
movq $0x0, 0x110(%rsp)
leaq 0x129f4(%rip), %rax     # 0x1d5c8
movq %rax, 0x118(%rsp)
callq 0x60a6
movq %rax, 0x120(%rsp)
movl $0x0, 0x24(%rsp)
leaq 0x12a88(%rip), %rax     # 0x1d680
cmpb $0x1, (%rax)
jne 0xac0b
leaq 0xbac7(%rip), %rdi      # 0x166cb
xorl %esi, %esi
callq 0xfb72
movq 0x8(%rsp), %rsi
movq 0x20(%rsi), %rax
movq %rax, 0x48(%rsp)
leaq 0x70(%rsp), %rdi
callq 0x13bf4
leaq 0x70(%rsp), %rdi
callq 0x13e05
movq %rax, 0x60(%rsp)
leaq 0x70(%rsp), %rdi
callq 0x13e05
movq %rax, %r14
leaq 0x70(%rsp), %rdi
callq 0x13e05
movq %rax, %rbx
leaq 0x70(%rsp), %rdi
callq 0x13e05
movq %rax, %r15
leaq 0x70(%rsp), %rdi
callq 0x13e05
movq %rax, %r12
movq %r14, %rdi
callq 0x13bed
movl %eax, 0x44(%rsp)
movq %rdx, 0x58(%rsp)
movq %r12, 0x28(%rsp)
movq %r15, 0x30(%rsp)
movq %rbx, %rdi
callq 0x13bed
movl %eax, 0x40(%rsp)
movq %rdx, 0x50(%rsp)
movq 0x8(%rsp), %rdx
movq 0xa0(%rdx), %rax
movq 0x100(%rdx), %r15
movslq 0x8(%rax), %rcx
testq %rcx, %rcx
leaq 0x8(%rcx,%rax), %rsi
cmoveq %rcx, %rsi
movq %rsi, 0x10(%rsp)
movl 0x4(%rax), %ecx
movl %ecx, 0x1c(%rsp)
movslq 0xc(%rax), %rcx
testq %rcx, %rcx
leaq 0xc(%rcx,%rax), %rax
cmoveq %rcx, %rax
movq %rax, 0x38(%rsp)
movq 0x108(%rdx), %rbp
testq %rbp, %rbp
je 0xadd5
movq %rbp, %r13
shlq $0x6, %r13
addq %r15, %r13
bsrq %rbp, %rdx
xorl $0x3f, %edx
addl %edx, %edx
xorq $0x7e, %rdx
movq %r15, %rdi
movq %r13, %rsi
callq 0xc965
cmpq $0x11, %rbp
jl 0xadca
leaq 0x400(%r15), %r12
movq %r15, %rdi
movq %r12, %rsi
callq 0xce76
movq (%r12), %rax
movq 0x8(%r12), %rcx
movups 0x30(%r12), %xmm0
movaps %xmm0, 0xb0(%rsp)
movups 0x20(%r12), %xmm0
movaps %xmm0, 0xa0(%rsp)
movups 0x10(%r12), %xmm0
movaps %xmm0, 0x90(%rsp)
movq %r12, %rdx
cmpq -0x38(%r12), %rcx
jae 0xad90
movq %r12, %rsi
leaq -0x40(%rsi), %rdx
movups -0x40(%rsi), %xmm0
movups -0x30(%rsi), %xmm1
movups -0x20(%rsi), %xmm2
movups -0x10(%rsi), %xmm3
movups %xmm3, 0x30(%rsi)
movups %xmm2, 0x20(%rsi)
movups %xmm1, 0x10(%rsi)
movups %xmm0, (%rsi)
cmpq -0x78(%rsi), %rcx
movq %rdx, %rsi
jb 0xad64
movq %rax, (%rdx)
movq %rcx, 0x8(%rdx)
movaps 0x90(%rsp), %xmm0
movaps 0xa0(%rsp), %xmm1
movaps 0xb0(%rsp), %xmm2
movups %xmm0, 0x10(%rdx)
movups %xmm1, 0x20(%rdx)
movups %xmm2, 0x30(%rdx)
addq $0x40, %r12
cmpq %r13, %r12
jne 0xad24
jmp 0xadd5
movq %r15, %rdi
movq %r13, %rsi
callq 0xce76
movq 0x8(%rsp), %rax
movq 0xa8(%rax), %rax
testq %rax, %rax
je 0xae0b
movslq 0x8(%rax), %rcx
testq %rcx, %rcx
leaq 0x8(%rcx,%rax), %r9
cmoveq %rcx, %r9
movslq 0xc(%rax), %rcx
testq %rcx, %rcx
leaq 0xc(%rcx,%rax), %r11
cmoveq %rcx, %r11
movl 0x4(%rax), %eax
jmp 0xae13
xorl %eax, %eax
xorl %r11d, %r11d
xorl %r9d, %r9d
movq 0x10(%rsp), %rdx
movq 0x28(%rsp), %r10
leaq 0x20(%rsp), %rcx
movl $0x0, (%rcx)
movl %eax, %r13d
movq %rcx, 0x90(%rsp)
movq %r15, 0x98(%rsp)
movq 0x38(%rsp), %rsi
movq %rsi, 0xa0(%rsp)
movq %rdx, 0xa8(%rsp)
movq %r9, 0xb0(%rsp)
movl %eax, 0xb8(%rsp)
movq %r11, 0xc0(%rsp)
movq %r14, 0xc8(%rsp)
movq %rbx, 0xd0(%rsp)
movq 0x30(%rsp), %r8
movq %r8, 0xd8(%rsp)
movq %r10, 0xe0(%rsp)
movq %r14, 0xe8(%rsp)
movq %rbx, 0xf0(%rsp)
movq %r8, 0xf8(%rsp)
movq %r10, 0x100(%rsp)
leaq 0x158(%rsp), %rdi
movq %rcx, -0x30(%rdi)
movq %r9, 0x28(%rsp)
movq %r9, -0x28(%rdi)
movq %rdx, -0x20(%rdi)
movl 0x1c(%rsp), %ecx
movl %ecx, -0x18(%rdi)
movq %rsi, -0x10(%rdi)
movq %r11, 0x68(%rsp)
movq %r11, -0x8(%rdi)
movq %r14, (%rdi)
movq %rbx, 0x8(%rdi)
movq %r8, 0x10(%rdi)
movq %r10, 0x18(%rdi)
xorl %r12d, %r12d
testq %rbp, %rbp
je 0xb005
movq %r15, 0x30(%rsp)
movl $0x0, %ebx
testl %eax, %eax
je 0xb007
xorl %ebx, %ebx
xorl %r12d, %r12d
movq %rbp, %r15
movq %rbx, %rax
shlq $0x6, %rax
movq 0x30(%rsp), %rcx
movq 0x8(%rcx,%rax), %rax
subq 0x38(%rsp), %rax
shrq $0x3, %rax
imull $0x38e38e39, %eax, %eax # imm = 0x38E38E39
cltq
shlq $0x4, %rax
movq %r12, %r14
shlq $0x4, %r14
movq 0x10(%rsp), %rdi
movq (%rdi,%rax), %rcx
xorl %edx, %edx
movq 0x28(%rsp), %rsi
cmpq (%rsi,%r14), %rcx
seta %dl
sbbl $0x0, %edx
movq 0x8(%rdi,%rax), %rax
xorl %ebp, %ebp
cmpq 0x8(%rsi,%r14), %rax
seta %bpl
sbbl $0x0, %ebp
testl %edx, %edx
cmovnel %edx, %ebp
testl %ebp, %ebp
jle 0xafc8
addq %rsi, %r14
movl 0x1c(%rsp), %esi
movq %r14, %rdx
callq 0xd763
testq %rax, %rax
je 0xafe4
subq 0x10(%rsp), %rax
sarq $0x4, %rax
leaq (%rax,%rax,8), %rax
movq 0x38(%rsp), %rcx
leaq (%rcx,%rax,8), %rcx
leaq (%r12,%r12,8), %rax
movq 0x68(%rsp), %rdx
leaq 0x4(%rdx,%rax,4), %rdx
movl -0x4(%rdx), %esi
leaq 0x158(%rsp), %rdi
movq %r14, %r8
callq 0xd1c6
incl 0x20(%rsp)
incl 0x125fa(%rip)           # 0x1d5c0
jmp 0xafea
leaq 0x90(%rsp), %rdi
movq %rbx, %rsi
callq 0xcf9e
incq %rbx
xorl %eax, %eax
testl %ebp, %ebp
sete %al
jmp 0xafef
incl 0x125da(%rip)           # 0x1d5c4
movl $0x1, %eax
addq %rax, %r12
movq %r15, %rbp
cmpq %r15, %rbx
jae 0xb007
cmpq %r13, %r12
jb 0xaf0b
jmp 0xb007
xorl %ebx, %ebx
cmpq %rbp, %rbx
jae 0xb027
leaq 0x90(%rsp), %r14
movq %r14, %rdi
movq %rbx, %rsi
callq 0xcf9e
incq %rbx
cmpq %rbx, %rbp
jne 0xb014
subq %r12, %r13
jbe 0xb0ce
movq 0x128(%rsp), %rax
movq %rax, 0x10(%rsp)
movq 0x138(%rsp), %rbx
movl 0x140(%rsp), %ebp
movq 0x148(%rsp), %r14
movq 0x150(%rsp), %rax
leaq (%r12,%r12,8), %rcx
leaq (%rax,%rcx,4), %r15
addq $0x4, %r15
shlq $0x4, %r12
addq 0x130(%rsp), %r12
movq %rbx, %rdi
movl %ebp, %esi
movq %r12, %rdx
callq 0xd763
testq %rax, %rax
je 0xb0bb
subq %rbx, %rax
sarq $0x4, %rax
leaq (%rax,%rax,8), %rax
leaq (%r14,%rax,8), %rcx
movl -0x4(%r15), %esi
leaq 0x158(%rsp), %rdi
movq %r15, %rdx
movq %r12, %r8
callq 0xd1c6
movq 0x10(%rsp), %rax
incl (%rax)
incl 0x12507(%rip)           # 0x1d5c0
jmp 0xb0c1
incl 0x12503(%rip)           # 0x1d5c4
addq $0x24, %r15
addq $0x10, %r12
decq %r13
jne 0xb074
leaq 0x90(%rsp), %rsi
movl $0x6d99231c, (%rsi)     # imm = 0x6D99231C
movl $0x4, %edx
movq 0x60(%rsp), %rbx
movq %rbx, %rdi
callq 0x13b75
movl 0x20(%rsp), %eax
leaq 0x90(%rsp), %rsi
movl %eax, (%rsi)
movl $0x4, %edx
movq %rbx, %rdi
callq 0x13b75
movq %rbx, %rdi
movl 0x44(%rsp), %esi
movq 0x58(%rsp), %rdx
callq 0x13ba1
movq %rbx, %rdi
movl 0x40(%rsp), %esi
movq 0x50(%rsp), %rdx
callq 0x13ba1
movq 0x8(%rsp), %rax
leaq 0x60(%rax), %rdi
callq 0xf084
movq 0x8(%rsp), %rax
movq $0x0, 0xa8(%rax)
movq 0xa0(%rax), %rax
movslq 0x70(%rax), %rcx
testq %rcx, %rcx
leaq 0x70(%rcx,%rax), %rsi
cmoveq %rcx, %rsi
leaq 0x70(%rsp), %rdi
callq 0x13ccc
movl %eax, %ebx
movq 0x8(%rsp), %rax
movq 0xa0(%rax), %rax
movslq 0x70(%rax), %rcx
testq %rcx, %rcx
leaq 0x70(%rcx,%rax), %rdi
cmoveq %rcx, %rdi
testb %bl, %bl
je 0xb1a5
movslq 0x6c(%rax), %rcx
testq %rcx, %rcx
leaq 0x6c(%rcx,%rax), %rsi
cmoveq %rcx, %rsi
callq 0x61d0
movl %eax, %ebx
jmp 0xb1aa
callq 0x3600
leaq 0x70(%rsp), %rdi
callq 0x13c07
movq 0x8(%rsp), %rax
movq 0x48(%rsp), %rcx
movq %rcx, 0x20(%rax)
leaq 0x24(%rsp), %rdi
callq 0x5b82
leaq 0x110(%rsp), %rdi
callq 0x5bac
movl %ebx, %eax
addq $0x178, %rsp            # imm = 0x178
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
jmp 0xb225
jmp 0xb20a
jmp 0xb20a
jmp 0xb20a
jmp 0xb20a
jmp 0xb20a
jmp 0xb20a
jmp 0xb20a
jmp 0xb20a
jmp 0xb20a
jmp 0xb20a
jmp 0xb20a
jmp 0xb20a
movq %rax, %rbx
movq 0x8(%rsp), %rax
movq 0x48(%rsp), %rcx
movq %rcx, 0x20(%rax)
leaq 0x24(%rsp), %rdi
callq 0x5b82
leaq 0x110(%rsp), %rdi
callq 0x5bac
movq %rbx, %rdi
callq 0x35e0