// File: /workspace/github_cpp_makefile_star2_O1/moyix[P]pandalog_taint_parser/label_instr.cpp
// Function: main
int main(int argc, char **argv) {
    if (argc != 5) {
        fprintf(stderr, "usage: %s <log> <num_instr> <first_instr> <buckets>\n", argv[0]);
        return 1;
    }

    num_instr = strtoull(argv[2], NULL, 0);
    first_instr = strtoull(argv[3], NULL, 0);
    buckets = atoi(argv[4]);
    bucket_to_ptr.resize(buckets);

    int fd = open(argv[1], O_RDONLY);
    struct stat st;
    stat(argv[1], &st);
    plog = (uint8_t *) mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
    //printf("Mapped at %p\n", plog);
    hdr = (PlHeader *)plog;
    printf("PandaLog v%u with directory at %" PRId64 " chunk size %x\n",
        hdr->version, hdr->dir_pos, hdr->chunk_size);
    dir = (PlDir *)(plog + hdr->dir_pos);
    //printf("Directory entries in pandalog: %u\n", dir->num_entries);
    total_chunks = dir->num_entries;
    chunks = (PlChunk *) malloc(sizeof(PlChunk) * total_chunks);
    //printf("Dumping directory:\n");
    for (int i = 0; i < total_chunks; i++) {
        chunks[i].start = dir->entries[i].start;
        if (i+1 != total_chunks)
            chunks[i].size = dir->entries[i+1].start - chunks[i].start;
        else
            chunks[i].size = hdr->dir_pos - chunks[i].start;
        //printf("  %zu - %zu\n", chunks[i].start, chunks[i].start+chunks[i].size);
    }

    int ncpu = sysconf(_SC_NPROCESSORS_ONLN);
    pthread_t *threads = (pthread_t *) malloc(sizeof(pthread_t)*ncpu);
    arg *thread_args = (arg *) malloc(sizeof(arg)*ncpu); 
    for (int i = 0; i < ncpu; i++) {
        thread_args[i].start = (total_chunks / ncpu) * i;
        thread_args[i].size = (i < ncpu - 1) ? 
            (total_chunks / ncpu) : (total_chunks - thread_args[i].start);
        //printf("Creating thread to process Chunks %u - %u\n", thread_args[i].start, thread_args[i].start+thread_args[i].size);
        pthread_create(&threads[i], NULL, process_chunks, &thread_args[i]);
    }
    pthread_t progress_thread;
    pthread_create(&progress_thread, NULL, progress_func, NULL);
    for (int i = 0; i < ncpu; i++) {
        pthread_join(threads[i], NULL);
    }
    pthread_join(progress_thread, NULL);

    FILE *f = fopen("label_instr.txt", "w");
    printf("Final pass to compute number of labels...\n");
    for (size_t i = 0; i < bucket_to_ptr.size(); i++) {
        std::set<int> full_set;
        for (auto ls : bucket_to_ptr[i]) full_set.insert(ptr_to_label[ls].begin(), ptr_to_label[ls].end());
        fprintf(f, "%zu", i*((num_instr-first_instr)/buckets)+first_instr);
        for (auto l : full_set) fprintf(f, " %d", l);
        fprintf(f, "\n");
    }
    fclose(f);

    return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xf8, %rsp
movq %rsi, %rbx
cmpl $0x5, %edi
jne 0x7b4c
movq 0x10(%rbx), %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x6430
movq %rax, 0x1cf57(%rip)     # 0x246c8
movq 0x18(%rbx), %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x6430
movq %rax, 0x1cf4b(%rip)     # 0x246d0
movq 0x20(%rbx), %rdi
callq 0x6520
movl %eax, 0x1cf2c(%rip)     # 0x246c0
movslq %eax, %rsi
leaq 0x1ceaa(%rip), %rdi     # 0x24648
callq 0x7c20
movq 0x8(%rbx), %rdi
xorl %esi, %esi
xorl %eax, %eax
callq 0x6230
movl %eax, %ebp
movq 0x8(%rbx), %rdi
leaq 0x68(%rsp), %rbx
movq %rbx, %rsi
callq 0x62f0
movq 0x30(%rbx), %rsi
xorl %edi, %edi
movl $0x1, %edx
movl $0x2, %ecx
movl %ebp, %r8d
xorl %r9d, %r9d
callq 0x65e0
movq %rax, 0x1ce1b(%rip)     # 0x24600
movq %rax, 0x1ce24(%rip)     # 0x24610
movl (%rax), %esi
movq 0x8(%rax), %rdx
movl 0x10(%rax), %ecx
leaq 0x1196d(%rip), %rdi     # 0x19169
xorl %eax, %eax
callq 0x6030
movq 0x1cdf6(%rip), %r14     # 0x24600
movq 0x1cdff(%rip), %rax     # 0x24610
movq 0x8(%rax), %rbx
leaq (%r14,%rbx), %rax
movq %rax, 0x1cdf8(%rip)     # 0x24618
movslq (%r14,%rbx), %r15
movl %r15d, 0x1ce91(%rip)    # 0x246bc
movq %r15, %rdi
shlq $0x4, %rdi
callq 0x6420
movq %rax, 0x1cdca(%rip)     # 0x24608
testq %r15, %r15
jle 0x7889
addq $0x8, %rax
leaq (%rbx,%r14), %rcx
addq $0x24, %rcx
shlq $0x3, %r15
leaq (%r15,%r15,2), %rdx
leaq (%r15,%r15,2), %rsi
addq $-0x18, %rsi
xorl %edi, %edi
movq -0x18(%rcx,%rdi), %r8
movq %r8, -0x8(%rax)
movq %rbx, %r9
cmpq %rdi, %rsi
je 0x7876
movq (%rcx,%rdi), %r9
subq %r8, %r9
movq %r9, (%rax)
addq $0x10, %rax
addq $0x18, %rdi
cmpq %rdi, %rdx
jne 0x7861
movl $0x54, %edi
callq 0x61e0
movq %rax, %rbx
movslq %ebx, %r14
leaq (,%r14,8), %r15
movq %r15, %rdi
callq 0x6420
movq %rax, 0x8(%rsp)
movq %r15, %rdi
callq 0x6420
testl %r14d, %r14d
jle 0x7925
movq %rax, %r15
leal -0x1(%rbx), %eax
cltq
movq %rax, 0x10(%rsp)
movl %ebx, %r14d
andl $0x7fffffff, %r14d      # imm = 0x7FFFFFFF
xorl %r12d, %r12d
movq %r15, %r13
movq 0x8(%rsp), %rbp
movl 0x1cdd9(%rip), %ecx     # 0x246bc
movl %ecx, %eax
cltd
idivl %ebx
movl %r12d, %edx
imull %eax, %edx
movl %edx, (%r15,%r12,8)
subl %edx, %ecx
cmpq 0x10(%rsp), %r12
cmovll %eax, %ecx
movl %ecx, 0x4(%r15,%r12,8)
movq %rbp, %rdi
xorl %esi, %esi
leaq -0x77f(%rip), %rdx      # 0x718e
movq %r13, %rcx
callq 0x6600
incq %r12
addq $0x8, %rbp
addq $0x8, %r13
cmpq %r12, %r14
jne 0x78dd
leaq -0x274(%rip), %rdx      # 0x76b8
leaq 0x28(%rsp), %rdi
xorl %esi, %esi
xorl %ecx, %ecx
callq 0x6600
testl %ebx, %ebx
movq 0x8(%rsp), %r15
jle 0x795f
andl $0x7fffffff, %ebx       # imm = 0x7FFFFFFF
xorl %r14d, %r14d
movq (%r15,%r14,8), %rdi
xorl %esi, %esi
callq 0x62e0
incq %r14
cmpq %r14, %rbx
jne 0x794c
movq 0x28(%rsp), %rdi
xorl %esi, %esi
callq 0x62e0
leaq 0x11829(%rip), %rdi     # 0x1919b
leaq 0x11832(%rip), %rsi     # 0x191ab
callq 0x63b0
movq %rax, %r14
leaq 0x11902(%rip), %rdi     # 0x1928a
callq 0x6510
movq 0x1ccb4(%rip), %rax     # 0x24648
cmpq %rax, 0x1ccb5(%rip)     # 0x24650
je 0x7b30
leaq 0x40(%rsp), %r15
leaq 0x38(%rsp), %r13
leaq 0x1ccae(%rip), %r12     # 0x24660
leaq 0x18(%rsp), %rbp
xorl %esi, %esi
movq %r14, 0x20(%rsp)
movl $0x0, 0x40(%rsp)
xorl %ecx, %ecx
movq %rcx, 0x48(%rsp)
movq %r15, 0x50(%rsp)
movq %r15, 0x58(%rsp)
movq %rcx, 0x60(%rsp)
movq %rsi, 0x8(%rsp)
leaq (%rsi,%rsi,2), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
addq $0x8, %rax
movq 0x10(%rax), %r14
movq %rax, 0x10(%rsp)
cmpq %rax, %r14
je 0x7a6b
movq 0x20(%r14), %rax
movq %rax, 0x18(%rsp)
movq %r12, %rdi
movq %rbp, %rsi
callq 0x7c9e
movq (%rax), %rbx
movq %r12, %rdi
movq %rbp, %rsi
callq 0x7c9e
movq 0x8(%rax), %r12
movq %r13, 0x30(%rsp)
cmpq %r12, %rbx
leaq 0x30(%rsp), %rbp
je 0x7a4d
movq %r13, %rdi
movq %r15, %rsi
movq %rbx, %rdx
movq %rbp, %rcx
callq 0x8686
addq $0x4, %rbx
cmpq %r12, %rbx
jne 0x7a33
movq %r14, %rdi
callq 0x6390
movq %rax, %r14
cmpq 0x10(%rsp), %rax
leaq 0x1cbfc(%rip), %r12     # 0x24660
leaq 0x18(%rsp), %rbp
jne 0x79fe
movq 0x1cc56(%rip), %rax     # 0x246c8
movq 0x1cc57(%rip), %rcx     # 0x246d0
subq %rcx, %rax
movslq 0x1cc3d(%rip), %rsi     # 0x246c0
xorl %edx, %edx
divq %rsi
imulq 0x8(%rsp), %rax
addq %rax, %rcx
movq 0x20(%rsp), %r14
movq %r14, %rdi
leaq 0x1170d(%rip), %rsi     # 0x191ad
movq %rcx, %rdx
xorl %eax, %eax
callq 0x6490
movq 0x50(%rsp), %rbx
cmpq %r15, %rbx
leaq 0x116f8(%rip), %r12     # 0x191b1
je 0x7adb
movl 0x20(%rbx), %edx
movq %r14, %rdi
movq %r12, %rsi
xorl %eax, %eax
callq 0x6490
movq %rbx, %rdi
callq 0x6390
movq %rax, %rbx
cmpq %r15, %rax
jne 0x7abb
movl $0xa, %edi
movq %r14, %rsi
callq 0x63f0
movq %r13, %rdi
callq 0x7d86
movq 0x8(%rsp), %rsi
incq %rsi
movq 0x1cb51(%rip), %rcx     # 0x24650
movq 0x1cb42(%rip), %rax     # 0x24648
subq %rax, %rcx
sarq $0x4, %rcx
movabsq $-0x5555555555555555, %rdx # imm = 0xAAAAAAAAAAAAAAAB
imulq %rdx, %rcx
cmpq %rcx, %rsi
leaq 0x1cb3b(%rip), %r12     # 0x24660
leaq 0x18(%rsp), %rbp
jb 0x79be
movq %r14, %rdi
callq 0x6350
xorl %eax, %eax
addq $0xf8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rbx, %rdi
callq 0x6660
movl $0x1, %eax
jmp 0x7b3a
jmp 0x7b5d
movq %rax, %rbx
leaq 0x38(%rsp), %rdi
callq 0x7d86
movq %rbx, %rdi
callq 0x65d0