// File: /workspace/github_c_makefile_star2_O0/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
movq %rsp, %rbp
subq $0x4e0, %rsp            # imm = 0x4E0
movq %rdi, -0x8(%rbp)
leaq 0x20802(%rip), %rdx     # 0x2f5b8
xorl %eax, %eax
movl %eax, -0x358(%rbp)
movl %eax, %esi
leaq -0x20(%rbp), %rdi
callq 0x7220
movl -0x358(%rbp), %edx
leaq 0x15969(%rip), %rsi     # 0x2473f
leaq -0x24(%rbp), %rdi
callq 0x67e0
jmp 0xede1
movq -0x8(%rbp), %rsi
addq $0x8, %rsi
leaq -0x48(%rbp), %rdi
callq 0x6e40
jmp 0xedf4
movq -0x8(%rbp), %rsi
leaq -0x68(%rbp), %rdi
callq 0x20e50
jmp 0xee03
leaq -0x68(%rbp), %rdi
callq 0x21190
movq %rax, -0x360(%rbp)
jmp 0xee15
movq -0x360(%rbp), %rax
movq %rax, -0x70(%rbp)
leaq -0x68(%rbp), %rdi
callq 0x21190
movq %rax, -0x368(%rbp)
jmp 0xee32
movq -0x368(%rbp), %rax
movq %rax, -0x78(%rbp)
leaq -0x68(%rbp), %rdi
callq 0x21190
movq %rax, -0x370(%rbp)
jmp 0xee4f
movq -0x370(%rbp), %rax
movq %rax, -0x80(%rbp)
leaq -0x68(%rbp), %rdi
callq 0x21190
movq %rax, -0x378(%rbp)
jmp 0xee6c
movq -0x378(%rbp), %rax
movq %rax, -0x88(%rbp)
leaq -0x68(%rbp), %rdi
callq 0x21190
movq %rax, -0x380(%rbp)
jmp 0xee8c
movq -0x380(%rbp), %rax
movq %rax, -0x90(%rbp)
movq -0x78(%rbp), %rdi
callq 0x20e20
movq %rdx, -0x390(%rbp)
movl %eax, -0x384(%rbp)
jmp 0xeeb2
movq -0x390(%rbp), %rax
movl -0x384(%rbp), %ecx
movl %ecx, -0xa0(%rbp)
movq %rax, -0x98(%rbp)
movq -0x80(%rbp), %rdi
callq 0x20e20
movq %rdx, -0x3a0(%rbp)
movl %eax, -0x394(%rbp)
jmp 0xeee4
movq -0x3a0(%rbp), %rax
movl -0x394(%rbp), %ecx
movl %ecx, -0xb0(%rbp)
movq %rax, -0xa8(%rbp)
movq -0x8(%rbp), %rax
movq 0xa0(%rax), %rax
movl 0x4(%rax), %eax
movl %eax, -0xb4(%rbp)
movq -0x8(%rbp), %rax
movq 0xa0(%rax), %rdi
addq $0x8, %rdi
callq 0x144f0
movq %rax, -0x3a8(%rbp)
jmp 0xef2f
movq -0x3a8(%rbp), %rax
movq %rax, -0xc0(%rbp)
movq -0x8(%rbp), %rax
movq 0xa0(%rax), %rdi
addq $0xc, %rdi
callq 0x144d0
movq %rax, -0x3b0(%rbp)
jmp 0xef5a
movq -0x3b0(%rbp), %rax
movq %rax, -0xc8(%rbp)
movq -0x8(%rbp), %rax
movq 0x100(%rax), %rax
movq %rax, -0xd0(%rbp)
movq -0x8(%rbp), %rax
movq 0x108(%rax), %rax
movq %rax, -0xd8(%rbp)
movq -0xd0(%rbp), %rdi
movq -0xd8(%rbp), %rax
shlq $0x6, %rax
movq %rdi, %rsi
addq %rax, %rsi
callq 0xf5b0
jmp 0xefab
movq $0x0, -0xe8(%rbp)
movq $0x0, -0xf0(%rbp)
movl $0x0, -0xf4(%rbp)
movq -0x8(%rbp), %rax
movq 0xa8(%rax), %rax
movq %rax, -0x100(%rbp)
cmpq $0x0, -0x100(%rbp)
je 0xf087
movq -0x100(%rbp), %rdi
addq $0x8, %rdi
callq 0x144f0
movq %rax, -0x3b8(%rbp)
jmp 0xf004
movq -0x3b8(%rbp), %rax
movq %rax, -0xe8(%rbp)
movq -0x100(%rbp), %rdi
addq $0xc, %rdi
callq 0x14690
movq %rax, -0x3c0(%rbp)
jmp 0xf02b
movq -0x3c0(%rbp), %rax
movq %rax, -0xf0(%rbp)
movq -0x100(%rbp), %rax
movl 0x4(%rax), %eax
movl %eax, -0xf4(%rbp)
jmp 0xf087
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
jmp 0xf59a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
jmp 0xf591
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
leaq -0x48(%rbp), %rdi
callq 0x6f50
jmp 0xf591
movl $0x0, -0x104(%rbp)
movq -0x78(%rbp), %rax
movq %rax, -0x128(%rbp)
movq -0x80(%rbp), %rax
movq %rax, -0x120(%rbp)
movq -0x88(%rbp), %rax
movq %rax, -0x118(%rbp)
movq -0x90(%rbp), %rax
movq %rax, -0x110(%rbp)
movq -0x78(%rbp), %rax
movq %rax, -0x148(%rbp)
movq -0x80(%rbp), %rax
movq %rax, -0x140(%rbp)
movq -0x88(%rbp), %rax
movq %rax, -0x138(%rbp)
movq -0x90(%rbp), %rax
movq %rax, -0x130(%rbp)
leaq -0x104(%rbp), %rax
movq %rax, -0x1c0(%rbp)
movq -0xd0(%rbp), %rcx
movq %rcx, -0x1b8(%rbp)
movq -0xc8(%rbp), %rcx
movq %rcx, -0x1b0(%rbp)
movq -0xc0(%rbp), %rcx
movq %rcx, -0x1a8(%rbp)
movq -0xe8(%rbp), %rcx
movq %rcx, -0x1a0(%rbp)
movl -0xf4(%rbp), %ecx
movl %ecx, -0x198(%rbp)
movq -0xf0(%rbp), %rcx
movq %rcx, -0x190(%rbp)
movups -0x148(%rbp), %xmm0
movups -0x138(%rbp), %xmm1
movups %xmm1, -0x178(%rbp)
movups %xmm0, -0x188(%rbp)
movups -0x128(%rbp), %xmm0
movups -0x118(%rbp), %xmm1
movups %xmm1, -0x158(%rbp)
movups %xmm0, -0x168(%rbp)
movq %rax, -0x210(%rbp)
movq -0xe8(%rbp), %rax
movq %rax, -0x208(%rbp)
movq -0xc0(%rbp), %rax
movq %rax, -0x200(%rbp)
movl -0xb4(%rbp), %eax
movl %eax, -0x1f8(%rbp)
movq -0xc8(%rbp), %rax
movq %rax, -0x1f0(%rbp)
movq -0xf0(%rbp), %rax
movq %rax, -0x1e8(%rbp)
movups -0x128(%rbp), %xmm0
movups -0x118(%rbp), %xmm1
movups %xmm1, -0x1d0(%rbp)
movups %xmm0, -0x1e0(%rbp)
movq -0xd0(%rbp), %rax
movq %rax, -0x228(%rbp)
movq -0xc8(%rbp), %rax
movq %rax, -0x220(%rbp)
movq -0xc0(%rbp), %rax
movq %rax, -0x218(%rbp)
movq -0xe8(%rbp), %rax
movq %rax, -0x230(%rbp)
movq -0xd8(%rbp), %rdi
movq -0x150(%rbp), %rax
movq %rax, -0x240(%rbp)
movups -0x160(%rbp), %xmm0
movaps %xmm0, -0x250(%rbp)
movups -0x170(%rbp), %xmm0
movaps %xmm0, -0x260(%rbp)
movups -0x180(%rbp), %xmm0
movaps %xmm0, -0x270(%rbp)
movups -0x1c0(%rbp), %xmm0
movups -0x1b0(%rbp), %xmm1
movups -0x1a0(%rbp), %xmm2
movups -0x190(%rbp), %xmm3
movaps %xmm3, -0x280(%rbp)
movaps %xmm2, -0x290(%rbp)
movaps %xmm1, -0x2a0(%rbp)
movaps %xmm0, -0x2b0(%rbp)
movq -0x218(%rbp), %rax
movq %rax, -0x2c0(%rbp)
movups -0x228(%rbp), %xmm0
movaps %xmm0, -0x2d0(%rbp)
movl -0xf4(%rbp), %eax
movl %eax, %esi
movups -0x1d0(%rbp), %xmm0
movaps %xmm0, -0x2e0(%rbp)
movups -0x210(%rbp), %xmm0
movups -0x200(%rbp), %xmm1
movups -0x1f0(%rbp), %xmm2
movups -0x1e0(%rbp), %xmm3
movaps %xmm3, -0x2f0(%rbp)
movaps %xmm2, -0x300(%rbp)
movaps %xmm1, -0x310(%rbp)
movaps %xmm0, -0x320(%rbp)
movq -0x230(%rbp), %rax
movq %rax, -0x328(%rbp)
movq -0x328(%rbp), %rdx
movaps -0x2e0(%rbp), %xmm0
movq %rsp, %rax
movq %rax, -0x3c8(%rbp)
movups %xmm0, 0xd0(%rax)
movaps -0x320(%rbp), %xmm0
movaps -0x310(%rbp), %xmm1
movaps -0x300(%rbp), %xmm2
movaps -0x2f0(%rbp), %xmm3
movups %xmm3, 0xc0(%rax)
movups %xmm2, 0xb0(%rax)
movups %xmm1, 0xa0(%rax)
movups %xmm0, 0x90(%rax)
movq -0x2c0(%rbp), %rcx
movq %rcx, 0x88(%rax)
movaps -0x2d0(%rbp), %xmm0
movups %xmm0, 0x78(%rax)
movq -0x240(%rbp), %rcx
movq %rcx, 0x70(%rax)
movaps -0x250(%rbp), %xmm0
movups %xmm0, 0x60(%rax)
movaps -0x260(%rbp), %xmm0
movups %xmm0, 0x50(%rax)
movaps -0x270(%rbp), %xmm0
movups %xmm0, 0x40(%rax)
movaps -0x2b0(%rbp), %xmm0
movaps -0x2a0(%rbp), %xmm1
movaps -0x290(%rbp), %xmm2
movaps -0x280(%rbp), %xmm3
movups %xmm3, 0x30(%rax)
movups %xmm2, 0x20(%rax)
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
callq 0xf5f0
jmp 0xf3e9
movq -0x70(%rbp), %rdi
movl $0x6d99231c, %esi       # imm = 0x6D99231C
callq 0xbaa0
jmp 0xf3f9
movq -0x70(%rbp), %rdi
movl -0x104(%rbp), %esi
callq 0xbb00
jmp 0xf40a
movq -0x70(%rbp), %rdi
movups -0xa0(%rbp), %xmm0
movaps %xmm0, -0x340(%rbp)
movl -0x340(%rbp), %esi
movq -0x338(%rbp), %rdx
callq 0x20db0
jmp 0xf430
movq -0x70(%rbp), %rdi
movups -0xb0(%rbp), %xmm0
movaps %xmm0, -0x350(%rbp)
movl -0x350(%rbp), %esi
movq -0x348(%rbp), %rdx
callq 0x20db0
jmp 0xf456
movq -0x8(%rbp), %rdi
addq $0x60, %rdi
callq 0x18c60
jmp 0xf465
movq -0x8(%rbp), %rax
movq $0x0, 0xa8(%rax)
movq -0x8(%rbp), %rax
movq 0xa0(%rax), %rdi
addq $0x70, %rdi
callq 0x6e20
movq %rax, -0x3d0(%rbp)
jmp 0xf491
movq -0x3d0(%rbp), %rsi
leaq -0x68(%rbp), %rdi
callq 0x20f60
movb %al, -0x3d1(%rbp)
jmp 0xf4a9
movb -0x3d1(%rbp), %al
andb $0x1, %al
movb %al, -0x351(%rbp)
testb $0x1, -0x351(%rbp)
je 0xf525
movq -0x8(%rbp), %rax
movq 0xa0(%rax), %rdi
addq $0x70, %rdi
callq 0x6e20
movq %rax, -0x3e0(%rbp)
jmp 0xf4dd
movq -0x8(%rbp), %rax
movq 0xa0(%rax), %rdi
addq $0x6c, %rdi
callq 0x6e20
movq %rax, -0x3e8(%rbp)
jmp 0xf4fa
movq -0x3e8(%rbp), %rsi
movq -0x3e0(%rbp), %rdi
callq 0x7f20
movb %al, -0x3e9(%rbp)
jmp 0xf515
movb -0x3e9(%rbp), %al
andb $0x1, %al
movb %al, -0x351(%rbp)
jmp 0xf54e
movq -0x8(%rbp), %rax
movq 0xa0(%rax), %rdi
addq $0x70, %rdi
callq 0x6e20
movq %rax, -0x3f8(%rbp)
jmp 0xf542
movq -0x3f8(%rbp), %rdi
callq 0x35e0
leaq -0x68(%rbp), %rdi
callq 0x20e80
jmp 0xf559
movb -0x351(%rbp), %al
movb %al, -0x3f9(%rbp)
leaq -0x48(%rbp), %rdi
callq 0x6f50
leaq -0x24(%rbp), %rdi
callq 0x6980
leaq -0x20(%rbp), %rdi
callq 0x7270
movb -0x3f9(%rbp), %al
andb $0x1, %al
addq $0x4e0, %rsp            # imm = 0x4E0
popq %rbp
retq
leaq -0x24(%rbp), %rdi
callq 0x6980
leaq -0x20(%rbp), %rdi
callq 0x7270
movq -0x30(%rbp), %rdi
callq 0x35c0
nopl (%rax)