// File: /workspace/github_c_makefile_star2_O3/hikalium[P]compilium/analyzer.c
// Function: AnalyzeNode
static void AnalyzeNode(struct Node *node, struct SymbolEntry **ctx) {
  assert(node);
  if (node->type == kASTList && !node->op) {
    for (int i = 0; i < GetSizeOfList(node); i++) {
      AnalyzeNode(GetNodeAt(node, i), ctx);
    }
    return;
  }
  if (node->type == kASTExprFuncCall) {
    node->stack_size_needed = (GetLastLocalVarOffset(*ctx) + 0xF) & ~0xF;
    AllocReg(node);
    AnalyzeNode(node->func_expr, ctx);
    FreeReg(node->func_expr->reg);
    node->expr_type =
        GetReturnTypeOfFunction(GetTypeWithoutAttr(node->func_expr->expr_type));
    for (int i = 0; i < GetSizeOfList(node->arg_expr_list); i++) {
      struct Node *n = GetNodeAt(node->arg_expr_list, i);
      AnalyzeNode(n, ctx);
      FreeReg(n->reg);
    }
    return;
  } else if (node->type == kASTFuncDef) {
    AddFuncDef(ctx, CreateTokenStr(node->func_name_token), node);
    struct SymbolEntry *saved_ctx = *ctx;
    struct Node *arg_type_list = GetArgTypeList(node->func_type);
    assert(arg_type_list);
    node->arg_var_list = AllocList();
    for (int i = 0; i < GetSizeOfList(arg_type_list); i++) {
      struct Node *arg_type_with_attr = GetNodeAt(arg_type_list, i);
      struct Node *arg_ident_token =
          GetIdentifierTokenFromTypeAttr(arg_type_with_attr);
      if (!arg_ident_token) {
        PushToList(node->arg_var_list, NULL);
        continue;
      }
      struct Node *arg_type = GetTypeWithoutAttr(arg_type_with_attr);
      assert(arg_type);
      struct Node *local_var =
          AddLocalVar(ctx, CreateTokenStr(arg_ident_token), arg_type);
      PushToList(node->arg_var_list, local_var);
    }
    assert(!in_function);
    in_function = node;
    AnalyzeNode(node->func_body, ctx);
    in_function = NULL;
    *ctx = saved_ctx;
    return;
  }
  assert(node->op);
  if (node->type == kASTExpr) {
    if (IsTokenWithType(node->op, kTokenIntegerConstant) ||
        IsTokenWithType(node->op, kTokenCharLiteral)) {
      AllocReg(node);
      node->expr_type = CreateTypeBase(CreateToken("int"));
      return;
    } else if (IsTokenWithType(node->op, kTokenStringLiteral)) {
      AllocReg(node);
      node->expr_type = CreateTypePointer(CreateTypeBase(CreateToken("char")));
      return;
    } else if (IsEqualTokenWithCStr(node->op, "(")) {
      AnalyzeNode(node->right, ctx);
      node->reg = node->right->reg;
      node->expr_type = node->right->expr_type;
      return;
    } else if (IsEqualTokenWithCStr(node->op, "[")) {
      AnalyzeNode(node->left, ctx);
      AnalyzeNode(node->right, ctx);
      node->reg = node->left->reg;
      FreeReg(node->right->reg);
      assert(node->left->expr_type);
      struct Node *left_type = GetTypeWithoutAttr(node->left->expr_type);
      if (left_type->type == kTypeArray) {
        node->expr_type = CreateTypeLValue(left_type->type_array_type_of);
      } else if (left_type->type == kTypePointer) {
        node->expr_type = CreateTypeLValue(left_type->right);
      } else {
        assert(false);
      }
      return;
    } else if (IsEqualTokenWithCStr(node->op, ".") ||
               IsEqualTokenWithCStr(node->op, "->")) {
      AnalyzeNode(node->left, ctx);
      node->reg = node->left->reg;
      PrintASTNode(node->left->expr_type);
      assert(node->right && node->right->type == kNodeToken);
      struct Node *struct_type = NULL;
      if (IsEqualTokenWithCStr(node->op, ".")) {
        if (GetTypeWithoutAttr(node->left->expr_type)->type != kTypeStruct) {
          ErrorWithToken(node->op, "left operand is not a struct");
        }
        struct_type = node->left->expr_type;
      }
      if (IsEqualTokenWithCStr(node->op, "->")) {
        struct Node *left_type = GetTypeWithoutAttr(node->left->expr_type);
        PrintASTNode(left_type);
        assert(left_type->type == kTypePointer);
        struct Node *left_deref_type = left_type->right;
        assert(left_deref_type->type == kTypeStruct);
        struct_type = left_deref_type;
      }
      assert(struct_type);
      struct Node *member = FindStructMember(struct_type, node->right);
      if (!member) {
        ErrorWithToken(node->right, "Member name not found in struct");
      }
      PrintASTNode(member);
      node->byte_offset = member->struct_member_ent_ofs;
      node->expr_type =
          CreateTypeLValue(GetTypeWithoutAttr(member->struct_member_ent_type));
      return;
    } else if (IsTokenWithType(node->op, kTokenIdent)) {
      struct Node *ident_info = FindLocalVar(*ctx, node->op);
      if (ident_info) {
        node->byte_offset = ident_info->byte_offset;
        AllocReg(node);
        enum NodeType expr_type =
            GetTypeWithoutAttr(ident_info->expr_type)->type;
        if (expr_type == kTypeStruct || expr_type == kTypeArray) {
          node->expr_type = ident_info->expr_type;
          return;
        }
        node->expr_type = CreateTypeLValue(ident_info->expr_type);
        return;
      }
      struct Node *global_var_type = FindGlobalVar(*ctx, node->op);
      if (global_var_type) {
        AllocReg(node);
        node->expr_type = CreateTypeLValue(global_var_type);
        return;
      }
      struct Node *external_var_type = FindExternVar(*ctx, node->op);
      if (external_var_type) {
        AllocReg(node);
        node->expr_type = CreateTypeLValue(external_var_type);
        return;
      }
      struct Node *func_def = FindFuncDef(*ctx, node->op);
      if (func_def) {
        AllocReg(node);
        node->expr_type = func_def->func_type;
        return;
      }
      struct Node *func_decl_type = FindFuncDeclType(*ctx, node->op);
      if (func_decl_type) {
        AllocReg(node);
        node->expr_type = GetTypeWithoutAttr(func_decl_type);
        return;
      }
      ErrorWithToken(node->op, "Unknown identifier");
    } else if (node->cond) {
      AnalyzeNode(node->cond, ctx);
      AnalyzeNode(node->left, ctx);
      AnalyzeNode(node->right, ctx);
      FreeReg(node->left->reg);
      FreeReg(node->right->reg);
      assert(
          IsSameTypeExceptAttr(node->left->expr_type, node->right->expr_type));
      node->reg = node->cond->reg;
      node->expr_type = GetRValueType(node->right->expr_type);
      return;
    } else if (!node->left && node->right) {
      AnalyzeNode(node->right, ctx);
      if (IsEqualTokenWithCStr(node->op, "--") ||
          IsEqualTokenWithCStr(node->op, "++")) {
        assert(IsLValueType(node->right->expr_type));
        node->reg = node->right->reg;
        node->expr_type = GetRValueType(node->right->expr_type);
        return;
      }
      if (IsTokenWithType(node->op, kTokenKwSizeof)) {
        FreeReg(node->right->reg);
        AllocReg(node);
        node->expr_type = CreateTypeBase(CreateToken("int"));
        return;
      }
      node->reg = node->right->reg;
      if (IsEqualTokenWithCStr(node->op, "&")) {
        node->expr_type =
            CreateTypePointer(GetRValueType(node->right->expr_type));
        return;
      }
      if (IsEqualTokenWithCStr(node->op, "*")) {
        struct Node *rtype = GetRValueType(node->right->expr_type);
        assert(rtype && rtype->type == kTypePointer);
        node->expr_type = CreateTypeLValue(rtype->right);
        return;
      }
      node->expr_type = GetRValueType(node->right->expr_type);
      return;
    } else if (node->left && !node->right) {
      // Postfix op
      if (IsEqualTokenWithCStr(node->op, "++") ||
          IsEqualTokenWithCStr(node->op, "--")) {
        AnalyzeNode(node->left, ctx);
        assert(IsLValueType(node->left->expr_type));
        node->reg = node->left->reg;
        node->expr_type = GetRValueType(node->left->expr_type);
        return;
      }
    } else if (node->left && node->right) {
      AnalyzeNode(node->left, ctx);
      AnalyzeNode(node->right, ctx);
      if (IsEqualTokenWithCStr(node->op, "=") ||
          IsEqualTokenWithCStr(node->op, ",")) {
        FreeReg(node->left->reg);
        node->reg = node->right->reg;
        node->expr_type = GetRValueType(node->right->expr_type);
        return;
      }
      FreeReg(node->right->reg);
      node->reg = node->left->reg;
      node->expr_type = GetRValueType(node->left->expr_type);
      return;
    }
    assert(false);
  }
  if (node->type == kASTExprStmt) {
    if (!node->left) return;
    AnalyzeNode(node->left, ctx);
    if (node->left->reg) FreeReg(node->left->reg);
    return;
  } else if (node->type == kASTList) {
    struct SymbolEntry *saved_ctx = *ctx;
    for (int i = 0; i < GetSizeOfList(node); i++) {
      AnalyzeNode(GetNodeAt(node, i), ctx);
    }
    *ctx = saved_ctx;
    return;
  } else if (node->type == kASTDecl) {
    struct Node *raw_type = CreateTypeInContext(*ctx, node->op, node->right);
    PrintASTNode(raw_type);
    assert(raw_type);
    struct Node *type_ident = NULL;
    if (raw_type && raw_type->type == kTypeAttrIdent) {
      type_ident = raw_type->left;
    }
    struct Node *type = GetTypeWithoutAttr(raw_type);
    assert(type);

    if (!in_function) {
      // Top-level definitions
      if (IsASTDeclOfTypedef(node)) {
        return;
      }
      if (type_ident && type->type == kTypeFunction) {
        AddFuncDeclType(ctx, CreateTokenStr(type_ident), raw_type);
        return;
      }
      if (!type_ident && type->type == kTypeStruct) {
        struct Node *spec = type->type_struct_spec;
        ResolveTypesOfMembersOfStruct(*ctx, spec);
        assert(type->tag);
        AddStructType(ctx, CreateTokenStr(type->tag), type);
        return;
      }
      assert(type_ident);
      if (IsASTDeclOfExtern(node)) {
        AddExternVar(ctx, CreateTokenStr(type_ident), type);
      } else {
        AddGlobalVar(ctx, CreateTokenStr(type_ident), type);
      }
      assert(node->right->type == kASTDecltor);
      if (node->right->decltor_init_expr) {
        assert(false);
      }
      return;
    }
    // Local definitions
    assert(type_ident);
    AddLocalVar(ctx, CreateTokenStr(type_ident), type);
    assert(node->right->type == kASTDecltor);
    if (node->right->decltor_init_expr) {
      struct Node *left_expr = AllocNode(kASTExpr);
      left_expr->op = type_ident;
      node->right->decltor_init_expr->left = left_expr;
      AnalyzeNode(node->right->decltor_init_expr, ctx);
      FreeReg(node->right->decltor_init_expr->reg);
    }
    return;
  } else if (node->type == kASTJumpStmt) {
    if (IsTokenWithType(node->op, kTokenKwBreak) ||
        IsTokenWithType(node->op, kTokenKwContinue)) {
      return;
    }
    if (IsTokenWithType(node->op, kTokenKwReturn)) {
      if (!node->right) return;
      AnalyzeNode(node->right, ctx);
      FreeReg(node->right->reg);
      return;
    }
  } else if (node->type == kASTSelectionStmt) {
    if (IsTokenWithType(node->op, kTokenKwIf)) {
      AnalyzeNode(node->cond, ctx);
      FreeReg(node->cond->reg);
      AnalyzeNode(node->if_true_stmt, ctx);
      if (node->if_else_stmt) {
        AnalyzeNode(node->if_else_stmt, ctx);
      }
      return;
    }
  } else if (node->type == kASTForStmt) {
    if (node->init) {
      AnalyzeNode(node->init, ctx);
      if (node->init->reg) FreeReg(node->init->reg);
    }
    if (node->cond) {
      AnalyzeNode(node->cond, ctx);
      FreeReg(node->cond->reg);
    }
    if (node->updt) {
      AnalyzeNode(node->updt, ctx);
      FreeReg(node->updt->reg);
    }
    AnalyzeNode(node->body, ctx);
    return;
  } else if (node->type == kASTWhileStmt) {
    AnalyzeNode(node->cond, ctx);
    FreeReg(node->cond->reg);
    AnalyzeNode(node->body, ctx);
    return;
  }
  ErrorWithToken(node->op, "AnalyzeNode: Not implemented");
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
testq %rdi, %rdi
je 0x3190
movq %rsi, %r14
movq %rdi, %rbx
leaq 0x7fd0(%rip), %r15      # 0xb004
leaq 0xe295(%rip), %r12      # 0x112d0
leaq 0xe2be(%rip), %r13      # 0x11300
movl (%rbx), %eax
cmpl $0x5, %eax
je 0x31a8
cmpl $0x10, %eax
je 0x32c0
cmpl $0x6, %eax
je 0x3279
movq 0x10(%rbx), %rsi
testq %rsi, %rsi
je 0x3aeb
addl $-0x4, %eax
cmpl $0xb, %eax
ja 0x3b2b
movslq (%r15,%rax,4), %rax
addq %r15, %rax
jmpq *%rax
movq %rsi, %rdi
movl $0xc, %esi
callq 0x90d3
testb %al, %al
je 0x3b2b
movq 0x30(%rbx), %rdi
movq %r14, %rsi
callq 0x3013
movq 0x30(%rbx), %rax
movl 0x4(%rax), %eax
leal -0x1(%rax), %ecx
cmpl $0xa, %ecx
jae 0x3a6e
movl $0x0, (%r12,%rax,4)
movq $0x0, (%r13,%rax,8)
movq 0x48(%rbx), %rdi
movq %r14, %rsi
callq 0x3013
movq 0x50(%rbx), %rbx
testq %rbx, %rbx
jne 0x3187
jmp 0x375c
movq 0x30(%rbx), %rdi
movq %r14, %rsi
callq 0x3013
movq 0x30(%rbx), %rax
jmp 0x3161
movq 0x28(%rbx), %rdi
testq %rdi, %rdi
je 0x3117
movq %r14, %rsi
callq 0x3013
movq 0x28(%rbx), %rax
movl 0x4(%rax), %edi
testl %edi, %edi
je 0x3117
callq 0x3e73
movq 0x30(%rbx), %rdi
testq %rdi, %rdi
je 0x314c
movq %r14, %rsi
callq 0x3013
movq 0x30(%rbx), %rax
movl 0x4(%rax), %eax
leal -0x1(%rax), %ecx
cmpl $0xa, %ecx
jae 0x3a6e
movl $0x0, (%r12,%rax,4)
movq $0x0, (%r13,%rax,8)
movq 0x38(%rbx), %rdi
testq %rdi, %rdi
je 0x3183
movq %r14, %rsi
callq 0x3013
movq 0x38(%rbx), %rax
movl 0x4(%rax), %eax
leal -0x1(%rax), %ecx
cmpl $0xa, %ecx
jae 0x3a6e
movl %eax, %eax
movl $0x0, (%r12,%rax,4)
movq $0x0, (%r13,%rax,8)
movq 0x40(%rbx), %rbx
testq %rbx, %rbx
jne 0x3042
leaq 0x7e9d(%rip), %rdi      # 0xb034
leaq 0x7e9b(%rip), %rsi      # 0xb039
movl $0x26, %edx
callq 0x46d0
movq (%r14), %rdi
callq 0x8d44
addl $0xf, %eax
andl $-0x10, %eax
movl %eax, 0xc8(%rbx)
movq %rbx, %rdi
callq 0x3e3c
movq 0xb0(%rbx), %rdi
movq %r14, %rsi
callq 0x3013
movq 0xb0(%rbx), %rax
movl 0x4(%rax), %ecx
leal -0x1(%rcx), %edx
cmpl $0xa, %edx
jae 0x3a6e
movl $0x0, (%r12,%rcx,4)
movq $0x0, (%r13,%rcx,8)
movq 0x8(%rax), %rdi
callq 0xa0a1
movq %rax, %rdi
callq 0x4275
movq %rax, 0x8(%rbx)
movq 0xb8(%rbx), %rdi
callq 0x48ee
testl %eax, %eax
jle 0x375c
xorl %ebp, %ebp
movq 0xb8(%rbx), %rdi
movl %ebp, %esi
callq 0x4918
movq %rax, %r15
movq %rax, %rdi
movq %r14, %rsi
callq 0x3013
movl 0x4(%r15), %eax
leal -0x1(%rax), %ecx
cmpl $0xa, %ecx
jae 0x3a6e
movl $0x0, (%r12,%rax,4)
movq $0x0, (%r13,%rax,8)
incl %ebp
movq 0xb8(%rbx), %rdi
callq 0x48ee
cmpl %eax, %ebp
jl 0x3225
jmp 0x375c
cmpq $0x0, 0x10(%rbx)
je 0x33bc
movq (%r14), %r15
movq %rbx, %rdi
callq 0x48ee
testl %eax, %eax
jle 0x32b8
xorl %ebp, %ebp
movq %rbx, %rdi
movl %ebp, %esi
callq 0x4918
movq %rax, %rdi
movq %r14, %rsi
callq 0x3013
incl %ebp
movq %rbx, %rdi
callq 0x48ee
cmpl %eax, %ebp
jl 0x3295
movq %r15, (%r14)
jmp 0x375c
movq 0xe0(%rbx), %rdi
callq 0x91d7
movq %r14, %rdi
movq %rax, %rsi
movq %rbx, %rdx
callq 0x8ee6
movq (%r14), %rax
movq %rax, (%rsp)
movq 0xd8(%rbx), %rdi
callq 0x429d
testq %rax, %rax
je 0x3c2c
movq %rax, %r15
xorl %r12d, %r12d
xorl %eax, %eax
callq 0x47d2
movq %rax, 0xc0(%rbx)
movq %r15, %rdi
callq 0x48ee
testl %eax, %eax
jle 0x3381
movq %r15, %rdi
movl %r12d, %esi
callq 0x4918
movq %rax, %rbp
movq %rax, %rdi
callq 0xa0c1
testq %rax, %rax
je 0x3363
movq %rax, %r13
movq %rbp, %rdi
callq 0xa0a1
testq %rax, %rax
je 0x3b43
movq %rax, %rbp
movq %r13, %rdi
callq 0x91d7
movq %r14, %rdi
movq %rax, %rsi
movq %rbp, %rdx
callq 0x8d85
movq %rax, %rsi
jmp 0x3365
xorl %esi, %esi
movq 0xc0(%rbx), %rdi
callq 0x485a
incl %r12d
movq %r15, %rdi
callq 0x48ee
cmpl %eax, %r12d
jl 0x3316
cmpq $0x0, 0xdf37(%rip)      # 0x112c0
jne 0x3c44
movq %rbx, 0xdf2a(%rip)      # 0x112c0
movq 0xd0(%rbx), %rdi
movq %r14, %rsi
callq 0x3013
movq $0x0, 0xdf10(%rip) # 0x112c0
movq (%rsp), %rax
movq %rax, (%r14)
jmp 0x375c
movq %rbx, %rdi
callq 0x48ee
testl %eax, %eax
jle 0x375c
xorl %ebp, %ebp
movq %rbx, %rdi
movl %ebp, %esi
callq 0x4918
movq %rax, %rdi
movq %r14, %rsi
callq 0x3013
incl %ebp
movq %rbx, %rdi
callq 0x48ee
cmpl %eax, %ebp
jl 0x33ce
jmp 0x375c
movq %rsi, %rdi
movl $0x3, %esi
callq 0x90d3
testb %al, %al
jne 0x341d
movq 0x10(%rbx), %rdi
movl $0x17, %esi
callq 0x90d3
testb %al, %al
je 0x35da
movq %rbx, %rdi
callq 0x3e3c
leaq 0x7c3c(%rip), %rdi      # 0xb068
callq 0x9898
movq %rax, %rdi
callq 0x41c7
movq %rax, 0x8(%rbx)
jmp 0x375c
movq 0x18(%rbx), %rdi
testq %rdi, %rdi
je 0x375c
movq %r14, %rsi
callq 0x3013
movq 0x18(%rbx), %rax
movl 0x4(%rax), %edi
testl %edi, %edi
jne 0x357e
jmp 0x375c
movq %rsi, %rdi
movl $0x5, %esi
callq 0x90d3
testb %al, %al
jne 0x375c
leaq 0x10(%rbx), %r15
movq (%r15), %rdi
movl $0x8, %esi
callq 0x90d3
testb %al, %al
jne 0x375c
movq (%r15), %rdi
movl $0xf, %esi
callq 0x90d3
testb %al, %al
je 0x3b32
movq 0x20(%rbx), %rdi
testq %rdi, %rdi
je 0x375c
movq %r14, %rsi
callq 0x3013
movq 0x20(%rbx), %rax
jmp 0x357b
movq (%r14), %rdi
movq 0x20(%rbx), %rdx
callq 0xa65b
movq %rax, %r13
movq %rax, %rdi
callq 0x441a
testq %r13, %r13
je 0x3c5c
cmpl $0x18, (%r13)
jne 0x34f9
movq 0x18(%r13), %r12
jmp 0x34fc
xorl %r12d, %r12d
movq %r13, %rdi
callq 0xa0a1
testq %rax, %rax
je 0x3c74
movq %rax, %r15
cmpq $0x0, 0xdda8(%rip)      # 0x112c0
je 0x3591
testq %r12, %r12
je 0x3c8c
movq %r12, %rdi
callq 0x91d7
movq %r14, %rdi
movq %rax, %rsi
movq %r15, %rdx
callq 0x8d85
movq 0x20(%rbx), %rax
cmpl $0xc, (%rax)
jne 0x3ca4
cmpq $0x0, 0x58(%rax)
je 0x375c
movl $0x4, %edi
callq 0x3f11
movq %r12, 0x10(%rax)
movq 0x20(%rbx), %rcx
movq 0x58(%rcx), %rdi
movq %rax, 0x18(%rdi)
movq %r14, %rsi
callq 0x3013
movq 0x20(%rbx), %rax
movq 0x58(%rax), %rax
movl 0x4(%rax), %edi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x3e73
movq %rbx, %rdi
callq 0x3ec3
testb %al, %al
jne 0x375c
movl (%r15), %eax
testq %r12, %r12
je 0x364c
cmpl $0x17, %eax
jne 0x3695
movq %r12, %rdi
callq 0x91d7
movq %r14, %rdi
movq %rax, %rsi
movq %r13, %rdx
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x8f82
movq 0x10(%rbx), %rdi
movl $0x18, %esi
callq 0x90d3
testb %al, %al
je 0x3615
movq %rbx, %rdi
callq 0x3e3c
leaq 0x7a71(%rip), %rdi      # 0xb06c
callq 0x9898
movq %rax, %rdi
callq 0x41c7
movq %rax, %rdi
callq 0x4205
jmp 0x3439
movq 0x10(%rbx), %rdi
leaq 0x7fa4(%rip), %rsi      # 0xb5c4
callq 0x9210
testl %eax, %eax
je 0x36c3
movq 0x20(%rbx), %rdi
movq %r14, %rsi
callq 0x3013
movq 0x20(%rbx), %rax
movl 0x4(%rax), %ecx
movl %ecx, 0x4(%rbx)
movq 0x8(%rax), %rax
jmp 0x3439
cmpl $0x19, %eax
jne 0x3cbc
movq 0xf0(%r15), %rsi
movq (%r14), %rdi
callq 0x8d28
movq 0xe8(%r15), %rdi
testq %rdi, %rdi
je 0x3cd4
callq 0x91d7
movq %r14, %rdi
movq %rax, %rsi
movq %r15, %rdx
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x901e
movq %rbx, %rdi
callq 0x3eea
movl %eax, %ebp
movq %r12, %rdi
callq 0x91d7
movq %r14, %rdi
movq %rax, %rsi
movq %r15, %rdx
testb %bpl, %bpl
je 0x373f
callq 0x2d89
jmp 0x3744
movq 0x10(%rbx), %rdi
leaq 0x7ecb(%rip), %rsi      # 0xb599
callq 0x9210
testl %eax, %eax
je 0x376b
movq 0x18(%rbx), %rdi
movq %r14, %rsi
callq 0x3013
movq 0x20(%rbx), %rdi
movq %r14, %rsi
callq 0x3013
movq 0x18(%rbx), %rax
movq 0x20(%rbx), %rcx
movl 0x4(%rax), %eax
movl %eax, 0x4(%rbx)
movl 0x4(%rcx), %edi
callq 0x3e73
movq 0x18(%rbx), %rax
movq 0x8(%rax), %rdi
testq %rdi, %rdi
je 0x3d34
callq 0xa0a1
movl (%rax), %ecx
cmpl $0x16, %ecx
je 0x3c1e
cmpl $0x1a, %ecx
jne 0x3d5c
movq 0xf8(%rax), %rdi
jmp 0x3c22
callq 0x2cfe
movq 0x20(%rbx), %rax
cmpl $0xc, (%rax)
jne 0x3cec
cmpq $0x0, 0x58(%rax)
jne 0x3d04
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x10(%rbx), %rdi
leaq 0x7f2d(%rip), %rsi      # 0xb6a3
callq 0x9210
testl %eax, %eax
jne 0x3797
movq 0x10(%rbx), %rdi
leaq 0x7903(%rip), %rsi      # 0xb08d
callq 0x9210
testl %eax, %eax
je 0x38a2
movq 0x18(%rbx), %rdi
movq %r14, %rsi
callq 0x3013
movq 0x18(%rbx), %rax
movl 0x4(%rax), %ecx
movl %ecx, 0x4(%rbx)
movq 0x8(%rax), %rdi
callq 0x441a
movq 0x20(%rbx), %rax
testq %rax, %rax
je 0x3d1c
cmpl $0x1, (%rax)
jne 0x3d1c
movq 0x10(%rbx), %rdi
leaq 0x7ecc(%rip), %rsi      # 0xb6a3
callq 0x9210
testl %eax, %eax
je 0x3800
movq 0x18(%rbx), %rax
movq 0x8(%rax), %rdi
callq 0xa0a1
cmpl $0x19, (%rax)
jne 0x3d74
movq 0x18(%rbx), %rax
movq 0x8(%rax), %r14
jmp 0x3803
xorl %r14d, %r14d
movq 0x10(%rbx), %rdi
leaq 0x787f(%rip), %rsi      # 0xb08d
callq 0x9210
testl %eax, %eax
je 0x385b
movq 0x18(%rbx), %rax
movq 0x8(%rax), %rdi
callq 0xa0a1
movq %rax, %r14
movq %rax, %rdi
callq 0x441a
cmpl $0x16, (%r14)
jne 0x3d84
movq 0x20(%r14), %r14
cmpl $0x19, (%r14)
je 0x3864
leaq 0x78b2(%rip), %rdi      # 0xb0fc
leaq 0x77e8(%rip), %rsi      # 0xb039
movl $0x86, %edx
callq 0x46d0
testq %r14, %r14
je 0x3d9c
movq 0x20(%rbx), %rsi
movq %r14, %rdi
callq 0x8c75
testq %rax, %rax
je 0x3d4c
movq %rax, %r14
movq %rax, %rdi
callq 0x441a
movl 0x80(%r14), %eax
movl %eax, 0xa8(%rbx)
movq 0x70(%r14), %rdi
callq 0xa0a1
movq %rax, %rdi
jmp 0x3c22
movq 0x10(%rbx), %rdi
movl $0x4, %esi
callq 0x90d3
testb %al, %al
je 0x3904
movq (%r14), %rdi
movq 0x10(%rbx), %rsi
callq 0x8ea2
testq %rax, %rax
je 0x3976
movq %rax, %r15
movl 0xa8(%rax), %eax
movl %eax, 0xa8(%rbx)
movq %rbx, %rdi
callq 0x3e3c
movq 0x8(%r15), %rdi
callq 0xa0a1
movl (%rax), %eax
addl $-0x19, %eax
movq 0x8(%r15), %rdi
cmpl $0x1, %eax
ja 0x3c22
movq %rdi, 0x8(%rbx)
jmp 0x375c
movq 0x30(%rbx), %rdi
testq %rdi, %rdi
je 0x39af
movq %r14, %rsi
callq 0x3013
movq 0x18(%rbx), %rdi
movq %r14, %rsi
callq 0x3013
movq 0x20(%rbx), %rdi
movq %r14, %rsi
callq 0x3013
movq 0x18(%rbx), %rax
movl 0x4(%rax), %edi
callq 0x3e73
movq 0x20(%rbx), %rax
movl 0x4(%rax), %edi
callq 0x3e73
movq 0x18(%rbx), %rax
movq 0x20(%rbx), %rcx
movq 0x8(%rax), %rdi
movq 0x8(%rcx), %rsi
callq 0x9f40
testl %eax, %eax
je 0x3db4
movq 0x20(%rbx), %rax
movq 0x30(%rbx), %rcx
movl 0x4(%rcx), %ecx
jmp 0x3ada
movq (%r14), %rdi
movq 0x10(%rbx), %rsi
callq 0x8e5e
testq %rax, %rax
jne 0x399c
movq (%r14), %rdi
movq 0x10(%rbx), %rsi
callq 0x8e1a
testq %rax, %rax
je 0x3b03
movq %rax, %r15
movq %rbx, %rdi
callq 0x3e3c
movq %r15, %rdi
jmp 0x3c22
movq 0x18(%rbx), %rax
movq 0x20(%rbx), %rdi
testq %rax, %rax
je 0x3a16
testq %rdi, %rdi
je 0x3a86
movq %rax, %rdi
movq %r14, %rsi
callq 0x3013
movq 0x20(%rbx), %rdi
movq %r14, %rsi
callq 0x3013
movq 0x10(%rbx), %rdi
leaq 0x83a6(%rip), %rsi      # 0xbd8d
callq 0x9210
testl %eax, %eax
jne 0x3a08
movq 0x10(%rbx), %rdi
leaq 0x781f(%rip), %rsi      # 0xb21a
callq 0x9210
testl %eax, %eax
je 0x3b5b
movq 0x18(%rbx), %rax
movl 0x4(%rax), %edi
callq 0x3e73
jmp 0x3a68
testq %rdi, %rdi
je 0x3dcc
movq %r14, %rsi
callq 0x3013
movq 0x10(%rbx), %rdi
leaq 0x7772(%rip), %rsi      # 0xb1a4
callq 0x9210
testl %eax, %eax
jne 0x3a53
movq 0x10(%rbx), %rdi
leaq 0x7761(%rip), %rsi      # 0xb1a7
callq 0x9210
testl %eax, %eax
je 0x3b99
movq 0x20(%rbx), %rax
movq 0x8(%rax), %rdi
callq 0xa0e8
testl %eax, %eax
je 0x3de4
movq 0x20(%rbx), %rax
jmp 0x3ad7
leaq 0x7858(%rip), %rdi      # 0xb2cd
leaq 0x75bd(%rip), %rsi      # 0xb039
movl $0x20, %edx
callq 0x46d0
movq 0x10(%rbx), %rdi
leaq 0x7716(%rip), %rsi      # 0xb1a7
callq 0x9210
testl %eax, %eax
jne 0x3ab2
movq 0x10(%rbx), %rdi
leaq 0x76ff(%rip), %rsi      # 0xb1a4
callq 0x9210
testl %eax, %eax
je 0x3dcc
movq 0x18(%rbx), %rdi
movq %r14, %rsi
callq 0x3013
movq 0x18(%rbx), %rax
movq 0x8(%rax), %rdi
callq 0xa0e8
testl %eax, %eax
je 0x3dfc
movq 0x18(%rbx), %rax
movl 0x4(%rax), %ecx
movl %ecx, 0x4(%rbx)
movq 0x8(%rax), %rdi
callq 0xa0d3
jmp 0x3439
leaq 0x808c(%rip), %rdi      # 0xbb7e
leaq 0x7540(%rip), %rsi      # 0xb039
movl $0x55, %edx
callq 0x46d0
movq (%r14), %rdi
movq 0x10(%rbx), %rsi
callq 0x8f3e
testq %rax, %rax
je 0x3b6c
movq %rax, %r15
movq %rbx, %rdi
callq 0x3e3c
movq 0xd8(%r15), %rax
jmp 0x3439
addq $0x10, %rbx
movq %rbx, %r15
movq (%r15), %rdi
leaq 0x76fe(%rip), %rsi      # 0xb23a
xorl %eax, %eax
callq 0x470c
leaq 0x7508(%rip), %rdi      # 0xb052
leaq 0x74e8(%rip), %rsi      # 0xb039
movl $0x49, %edx
callq 0x46d0
movq 0x20(%rbx), %rax
movl 0x4(%rax), %edi
callq 0x3e73
jmp 0x3ad3
movq (%r14), %rdi
movq 0x10(%rbx), %rsi
callq 0x8fda
testq %rax, %rax
je 0x3e14
movq %rax, %r14
movq %rbx, %rdi
callq 0x3e3c
movq %r14, %rdi
callq 0xa0a1
jmp 0x3439
movq 0x10(%rbx), %rdi
movl $0x10, %esi
callq 0x90d3
movq 0x20(%rbx), %rcx
movl 0x4(%rcx), %edi
testb %al, %al
je 0x3bbc
callq 0x3e73
jmp 0x341d
movl %edi, 0x4(%rbx)
movq 0x10(%rbx), %rdi
leaq 0x8132(%rip), %rsi      # 0xbcfc
callq 0x9210
testl %eax, %eax
je 0x3be5
movq 0x20(%rbx), %rax
movq 0x8(%rax), %rdi
callq 0xa0d3
jmp 0x3608
movq 0x10(%rbx), %rdi
leaq 0x75df(%rip), %rsi      # 0xb1cf
callq 0x9210
movl %eax, %ebp
movq 0x20(%rbx), %rax
movq 0x8(%rax), %rdi
callq 0xa0d3
testl %ebp, %ebp
je 0x3439
testq %rax, %rax
je 0x3e24
cmpl $0x16, (%rax)
jne 0x3e24
movq 0x20(%rax), %rdi
callq 0x41e6
jmp 0x3439
leaq 0x7411(%rip), %rdi      # 0xb044
leaq 0x73ff(%rip), %rsi      # 0xb039
movl $0x3e, %edx
callq 0x46d0
leaq 0x7410(%rip), %rdi      # 0xb05b
leaq 0x73e7(%rip), %rsi      # 0xb039
movl $0x4e, %edx
callq 0x46d0
leaq 0x75b9(%rip), %rdi      # 0xb21c
leaq 0x73cf(%rip), %rsi      # 0xb039
movl $0x10c, %edx            # imm = 0x10C
callq 0x46d0
leaq 0x73db(%rip), %rdi      # 0xb056
leaq 0x73b7(%rip), %rsi      # 0xb039
movl $0x112, %edx            # imm = 0x112
callq 0x46d0
leaq 0x759c(%rip), %rdi      # 0xb22f
leaq 0x739f(%rip), %rsi      # 0xb039
movl $0x131, %edx            # imm = 0x131
callq 0x46d0
leaq 0x810d(%rip), %rdi      # 0xbdb8
leaq 0x7387(%rip), %rsi      # 0xb039
movl $0x133, %edx            # imm = 0x133
callq 0x46d0
leaq 0x756c(%rip), %rdi      # 0xb22f
leaq 0x736f(%rip), %rsi      # 0xb039
movl $0x124, %edx            # imm = 0x124
callq 0x46d0
leaq 0x754a(%rip), %rdi      # 0xb225
leaq 0x7357(%rip), %rsi      # 0xb039
movl $0x120, %edx            # imm = 0x120
callq 0x46d0
leaq 0x80c5(%rip), %rdi      # 0xbdb8
leaq 0x733f(%rip), %rsi      # 0xb039
movl $0x12a, %edx            # imm = 0x12A
callq 0x46d0
leaq 0x737c(%rip), %rdi      # 0xb087
leaq 0x7327(%rip), %rsi      # 0xb039
movl $0x12c, %edx            # imm = 0x12C
callq 0x46d0
leaq 0x736d(%rip), %rdi      # 0xb090
leaq 0x730f(%rip), %rsi      # 0xb039
movl $0x79, %edx
callq 0x46d0
leaq 0x7336(%rip), %rdi      # 0xb071
leaq 0x72f7(%rip), %rsi      # 0xb039
movl $0x6a, %edx
callq 0x46d0
movq 0x20(%rbx), %rdi
leaq 0x73d6(%rip), %rsi      # 0xb12d
jmp 0x3b3c
leaq 0x7324(%rip), %rdi      # 0xb087
leaq 0x72cf(%rip), %rsi      # 0xb039
movl $0x71, %edx
callq 0x46d0
movq 0x10(%rbx), %rdi
leaq 0x7340(%rip), %rsi      # 0xb0bf
jmp 0x3b3c
leaq 0x7351(%rip), %rdi      # 0xb0dc
leaq 0x72a7(%rip), %rsi      # 0xb039
movl $0x84, %edx
callq 0x46d0
leaq 0x737e(%rip), %rdi      # 0xb121
leaq 0x728f(%rip), %rsi      # 0xb039
movl $0x89, %edx
callq 0x46d0
leaq 0x73a5(%rip), %rdi      # 0xb160
leaq 0x7277(%rip), %rsi      # 0xb039
movl $0xc1, %edx
callq 0x46d0
leaq 0x72b4(%rip), %rdi      # 0xb087
leaq 0x725f(%rip), %rsi      # 0xb039
movl $0xfb, %edx
callq 0x46d0
leaq 0x73bf(%rip), %rdi      # 0xb1aa
leaq 0x7247(%rip), %rsi      # 0xb039
movl $0xc9, %edx
callq 0x46d0
leaq 0x73f3(%rip), %rdi      # 0xb1f6
leaq 0x722f(%rip), %rsi      # 0xb039
movl $0xe7, %edx
callq 0x46d0
movq 0x10(%rbx), %rdi
leaq 0x732e(%rip), %rsi      # 0xb14d
jmp 0x3b3c
leaq 0x73a6(%rip), %rdi      # 0xb1d1
leaq 0x7207(%rip), %rsi      # 0xb039
movl $0xdc, %edx
callq 0x46d0