// File: /workspace/github_c_makefile_star2_O3/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, (%rsp)
movq $0x0, 0x110(%rsp)
leaq 0x12d98(%rip), %rax     # 0x1d5c8
movq %rax, 0x118(%rsp)
callq 0x5f2a
movq %rax, 0x120(%rsp)
movl $0x0, 0x24(%rsp)
leaq 0x12e2c(%rip), %rax     # 0x1d680
cmpb $0x1, (%rax)
jne 0xa867
leaq 0xbe5b(%rip), %rdi      # 0x166bb
xorl %esi, %esi
callq 0xf4a3
movq (%rsp), %rsi
movq 0x20(%rsi), %rax
movq %rax, 0x38(%rsp)
leaq 0x70(%rsp), %rdi
callq 0x134bc
leaq 0x70(%rsp), %rdi
callq 0x136d3
movq %rax, 0x50(%rsp)
leaq 0x70(%rsp), %rdi
callq 0x136d3
movq %rax, %r14
leaq 0x70(%rsp), %rdi
callq 0x136d3
movq %rax, %rbx
leaq 0x70(%rsp), %rdi
callq 0x136d3
movq %rax, %r15
leaq 0x70(%rsp), %rdi
callq 0x136d3
movq %rax, %r12
movq %r14, %rdi
callq 0x134b5
movl %eax, 0x34(%rsp)
movq %rdx, 0x48(%rsp)
movq %r12, 0x58(%rsp)
movq %r15, 0x28(%rsp)
movq %r14, 0x8(%rsp)
movq %rbx, %rdi
callq 0x134b5
movl %eax, 0x30(%rsp)
movq %rdx, 0x40(%rsp)
movq (%rsp), %rdx
movq 0xa0(%rdx), %rax
movq 0x100(%rdx), %r15
movslq 0x8(%rax), %rcx
testq %rcx, %rcx
leaq 0x8(%rcx,%rax), %r12
cmoveq %rcx, %r12
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, 0x10(%rsp)
movq 0x108(%rdx), %rbp
testq %rbp, %rbp
je 0xaa29
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 0xc4d5
cmpq $0x11, %rbp
jl 0xaa1e
leaq 0x400(%r15), %r14
movq %r15, %rdi
movq %r14, %rsi
callq 0xc9de
movq (%r14), %rax
movq 0x8(%r14), %rcx
movups 0x30(%r14), %xmm0
movaps %xmm0, 0xb0(%rsp)
movups 0x20(%r14), %xmm0
movaps %xmm0, 0xa0(%rsp)
movups 0x10(%r14), %xmm0
movaps %xmm0, 0x90(%rsp)
movq %r14, %rdx
cmpq -0x38(%r14), %rcx
jae 0xa9e4
movq %r14, %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 0xa9b8
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, %r14
cmpq %r13, %r14
jne 0xa97e
jmp 0xaa29
movq %r15, %rdi
movq %r13, %rsi
callq 0xc9de
movq (%rsp), %rax
movq 0xa8(%rax), %rax
testq %rax, %rax
je 0xaa5e
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 0xaa66
xorl %eax, %eax
xorl %r11d, %r11d
xorl %r9d, %r9d
movq 0x8(%rsp), %rdi
leaq 0x20(%rsp), %rcx
movl $0x0, (%rcx)
movl %eax, %r13d
movq %rcx, 0x90(%rsp)
movq %r15, 0x98(%rsp)
movq 0x10(%rsp), %rdx
movq %rdx, 0xa0(%rsp)
movq %r12, 0xa8(%rsp)
movq %r9, 0xb0(%rsp)
movl %eax, 0xb8(%rsp)
movq %r11, 0xc0(%rsp)
movq %rdi, 0xc8(%rsp)
movq %rbx, 0xd0(%rsp)
movq 0x28(%rsp), %r8
movq %r8, 0xd8(%rsp)
movq 0x58(%rsp), %r10
movq %r10, 0xe0(%rsp)
movq %rdi, 0xe8(%rsp)
movq %rbx, 0xf0(%rsp)
movq %r8, 0xf8(%rsp)
movq %r10, 0x100(%rsp)
leaq 0x158(%rsp), %rsi
movq %rcx, -0x30(%rsi)
movq %r9, 0x68(%rsp)
movq %r9, -0x28(%rsi)
movq %r12, -0x20(%rsi)
movl 0x1c(%rsp), %ecx
movl %ecx, -0x18(%rsi)
movq %rdx, -0x10(%rsi)
movq %r11, 0x60(%rsp)
movq %r11, -0x8(%rsi)
movq %rdi, (%rsi)
movq %rbx, 0x8(%rsi)
movq %r8, 0x10(%rsi)
movq %r10, 0x18(%rsi)
xorl %r14d, %r14d
testq %rbp, %rbp
je 0xac63
movq %r12, 0x8(%rsp)
movq %r15, 0x28(%rsp)
movl $0x0, %ebx
testl %eax, %eax
je 0xac65
xorl %ebx, %ebx
xorl %r12d, %r12d
movq %rbp, %r15
movq %rbx, %rax
shlq $0x6, %rax
movq 0x28(%rsp), %rcx
movq 0x8(%rcx,%rax), %rax
subq 0x10(%rsp), %rax
shrq $0x3, %rax
imull $0x38e38e39, %eax, %eax # imm = 0x38E38E39
cltq
shlq $0x4, %rax
movq %r12, %r14
shlq $0x4, %r14
movq 0x8(%rsp), %rdi
movq (%rdi,%rax), %rcx
xorl %edx, %edx
movq 0x68(%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 0xac20
addq %rsi, %r14
movl 0x1c(%rsp), %esi
movq %r14, %rdx
callq 0xd2a1
testq %rax, %rax
je 0xac3e
subq 0x8(%rsp), %rax
sarq $0x4, %rax
leaq (%rax,%rax,8), %rax
movq 0x10(%rsp), %rcx
leaq (%rcx,%rax,8), %rcx
leaq (%r12,%r12,8), %rax
movq 0x60(%rsp), %rdx
leaq 0x4(%rdx,%rax,4), %rdx
movl -0x4(%rdx), %esi
leaq 0x158(%rsp), %rdi
movq %r14, %r8
callq 0xcd2e
incl 0x20(%rsp)
incl 0x129a2(%rip)           # 0x1d5c0
jmp 0xac44
leaq 0x90(%rsp), %rdi
movq %rbx, %rsi
callq 0xcb06
incq %rbx
xorl %r14d, %r14d
testl %ebp, %ebp
sete %r14b
jmp 0xac4a
incl 0x12980(%rip)           # 0x1d5c4
movl $0x1, %r14d
addq %r12, %r14
movq %r15, %rbp
cmpq %r15, %rbx
jae 0xac65
movq %r14, %r12
cmpq %r13, %r14
jb 0xab63
jmp 0xac65
xorl %ebx, %ebx
cmpq %rbp, %rbx
jae 0xac85
leaq 0x90(%rsp), %r15
movq %r15, %rdi
movq %rbx, %rsi
callq 0xcb06
incq %rbx
cmpq %rbx, %rbp
jne 0xac72
subq %r14, %r13
jbe 0xad2c
movq 0x128(%rsp), %rax
movq %rax, 0x10(%rsp)
movq 0x138(%rsp), %rbx
movl 0x140(%rsp), %ebp
movq 0x148(%rsp), %r12
movq 0x150(%rsp), %rax
leaq (%r14,%r14,8), %rcx
leaq (%rax,%rcx,4), %r15
addq $0x4, %r15
shlq $0x4, %r14
addq 0x130(%rsp), %r14
movq %rbx, %rdi
movl %ebp, %esi
movq %r14, %rdx
callq 0xd2a1
testq %rax, %rax
je 0xad19
subq %rbx, %rax
sarq $0x4, %rax
leaq (%rax,%rax,8), %rax
leaq (%r12,%rax,8), %rcx
movl -0x4(%r15), %esi
leaq 0x158(%rsp), %rdi
movq %r15, %rdx
movq %r14, %r8
callq 0xcd2e
movq 0x10(%rsp), %rax
incl (%rax)
incl 0x128a9(%rip)           # 0x1d5c0
jmp 0xad1f
incl 0x128a5(%rip)           # 0x1d5c4
addq $0x24, %r15
addq $0x10, %r14
decq %r13
jne 0xacd2
leaq 0x90(%rsp), %rsi
movl $0x6d99231c, (%rsi)     # imm = 0x6D99231C
movl $0x4, %edx
movq 0x50(%rsp), %rbx
movq %rbx, %rdi
callq 0x1343d
movl 0x20(%rsp), %eax
leaq 0x90(%rsp), %rsi
movl %eax, (%rsi)
movl $0x4, %edx
movq %rbx, %rdi
callq 0x1343d
movq %rbx, %rdi
movl 0x34(%rsp), %esi
movq 0x48(%rsp), %rdx
callq 0x13469
movq %rbx, %rdi
movl 0x30(%rsp), %esi
movq 0x40(%rsp), %rdx
callq 0x13469
movq (%rsp), %rax
leaq 0x60(%rax), %rdi
callq 0xe9a4
movq (%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 0x1359a
movq (%rsp), %rcx
movq 0xa0(%rcx), %rcx
movslq 0x70(%rcx), %rdx
testq %rdx, %rdx
leaq 0x70(%rdx,%rcx), %rdi
cmoveq %rdx, %rdi
testb %al, %al
je 0xadfe
movslq 0x6c(%rcx), %rax
testq %rax, %rax
leaq 0x6c(%rax,%rcx), %rsi
cmoveq %rax, %rsi
callq 0x6054
movl %eax, %ebx
jmp 0xae05
callq 0x3600
xorl %ebx, %ebx
leaq 0x70(%rsp), %rdi
callq 0x134cf
movq (%rsp), %rax
movq 0x38(%rsp), %rcx
movq %rcx, 0x20(%rax)
leaq 0x24(%rsp), %rdi
callq 0x5a06
leaq 0x110(%rsp), %rdi
callq 0x5a30
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 0xae7e
jmp 0xae64
jmp 0xae64
jmp 0xae64
jmp 0xae64
jmp 0xae64
jmp 0xae64
jmp 0xae64
jmp 0xae64
jmp 0xae64
jmp 0xae64
jmp 0xae64
jmp 0xae64
movq %rax, %rbx
movq (%rsp), %rax
movq 0x38(%rsp), %rcx
movq %rcx, 0x20(%rax)
leaq 0x24(%rsp), %rdi
callq 0x5a06
leaq 0x110(%rsp), %rdi
callq 0x5a30
movq %rbx, %rdi
callq 0x35e0