// File: /workspace/github_c_makefile_star2_O2/ryvnf[P]czc/codegen.c
// Function: decl_pass
void decl_pass(struct ast *ast)
{
    size_t n_extern_defs;
    struct ast **extern_defs = ast_asts(ast, &n_extern_defs);

    for (size_t i = 0; i < n_extern_defs; ++i) {
        struct ast *extern_def = extern_defs[i];
        struct ast *loc;
        bool is_defined = false;

        switch (extern_def->tag) {
            case TYPE_DEF: {
                loc = extern_def;
                const char *name = ast_s(ast_ast(loc, 0));
                struct type *type = scope_get_type(current_scope, name);
                struct ast *def_type_ast = ast_ast(loc, 1);
                scope_add_typesym(current_scope, name, sym_new(loc));

                if (def_type_ast != NULL) {
                    struct type *def_type = type_from_ast(def_type_ast);

                    if (type != NULL && !type_equals(type, def_type))
                        fatal(extern_def->loc, "%s is redefined as a different type", name);

                    type_del(def_type);
                }

                continue;
            }
            case ASGN_EXPR:
            case FUNC_DEF:
                is_defined = true;
                loc = ast_ast(extern_def, 0);
                break;
            case ALIAS_DEF:
            case DECL: {
                loc = extern_def;
                break;
            }
            case SOURCE_FILE:
                decl_pass(extern_def);
                continue;
            case ALREADY_INCLUDED:
                continue;
            default:
                bug("%s should not be here", ast_tag_name(extern_def->tag));
        }
        const char *name = ast_s(ast_ast(loc, 0));
        struct sym *sym = scope_get_sym(current_scope, name);

        bool redecl = false;

        if (sym != NULL) {
            if (sym->tag == DECL_SYM && loc->tag == DECL) {
                struct decl_sym *decl_sym = (struct decl_sym *)sym;

                if (is_defined && decl_sym->is_defined)
                    fatal(extern_def->loc, "%s is redefined", name);

                struct type *type = type_from_ast(ast_ast(loc, 1));

                if (!type_equals(type, ((struct decl_sym *)sym)->type))
                    fatal(extern_def->loc, "%s is declared as different type", name);

                type_del(type);
            } else {
                fatal(extern_def->loc, "%s is redefined", name);
            }
            redecl = true;
        }

        struct sym *new_sym = sym_new(loc);

        if (is_defined)
            ((struct decl_sym *)new_sym)->is_defined = true;

        if (!redecl)
            scope_add_sym(current_scope, name, new_sym);
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
leaq 0x10(%rsp), %rsi
callq 0x270b
movq %rax, %r14
xorl %ebx, %ebx
movq %rax, 0x8(%rsp)
cmpq 0x10(%rsp), %rbx
jae 0x4456
movq (%r14,%rbx,8), %r15
movl (%r15), %edi
leal -0x4000(%rdi), %eax
cmpl $0x3, %eax
ja 0x42cf
leaq 0x739a(%rip), %rcx      # 0xb658
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
xorl %r12d, %r12d
movq %r15, %r13
jmp 0x4309
cmpl $0x7, %edi
je 0x444e
cmpl $0x4220, %edi           # imm = 0x4220
je 0x42f9
cmpl $0x4502, %edi           # imm = 0x4502
jne 0x4488
movq %r15, %rdi
callq 0x4278
jmp 0x444e
movq %r15, %rdi
xorl %esi, %esi
callq 0x26ce
movq %rax, %r13
movb $0x1, %r12b
movq %r13, %rdi
xorl %esi, %esi
callq 0x26ce
movq %rax, %rdi
callq 0x25da
movq %rax, %rsi
leaq 0xeabb(%rip), %rax      # 0x12de0
movq (%rax), %rdi
movq %rsi, (%rsp)
callq 0xa01a
movq %rax, %rbp
testq %rax, %rax
je 0x4397
cmpl $0x1, (%rbp)
jne 0x4465
cmpl $0x4000, (%r13)         # imm = 0x4000
jne 0x4465
testb %r12b, %r12b
je 0x4360
cmpb $0x1, 0x20(%rbp)
je 0x4465
movq %r13, %rdi
pushq $0x1
popq %rsi
callq 0x26ce
movq %rax, %rdi
callq 0xa849
movq %rax, %r14
movq 0x18(%rbp), %rsi
movq %rax, %rdi
callq 0xac35
testb %al, %al
je 0x4472
movq %r14, %rdi
callq 0xad4e
movq 0x8(%rsp), %r14
movq %r13, %rdi
callq 0xa250
testb %r12b, %r12b
je 0x43a8
movb $0x1, 0x20(%rax)
testq %rbp, %rbp
jne 0x444e
leaq 0xea28(%rip), %rcx      # 0x12de0
movq (%rcx), %rdi
movq (%rsp), %rsi
movq %rax, %rdx
callq 0xa009
jmp 0x444e
movq %r15, %rdi
xorl %esi, %esi
callq 0x26ce
movq %rax, %rdi
callq 0x25da
movq %rax, %r12
leaq 0xe9f8(%rip), %r14      # 0x12de0
movq (%r14), %rdi
movq %rax, %rsi
callq 0xa08f
movq %rax, %r13
movq %r15, %rdi
pushq $0x1
popq %rsi
callq 0x26ce
movq %rax, %rbp
movq (%r14), %r14
movq %r15, %rdi
callq 0xa250
movq %r14, %rdi
movq 0x8(%rsp), %r14
movq %r12, %rsi
movq %rax, %rdx
callq 0xa011
testq %rbp, %rbp
je 0x444e
movq %rbp, %rdi
callq 0xa849
movq %rax, %rbp
testq %r13, %r13
je 0x4446
movq %r13, %rdi
movq %rbp, %rsi
callq 0xac35
testb %al, %al
je 0x449e
movq %rbp, %rdi
callq 0xad4e
incq %rbx
jmp 0x429a
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x8(%r15), %rdi
leaq 0x742e(%rip), %rsi      # 0xb89e
jmp 0x447d
movq 0x8(%r15), %rdi
leaq 0x7431(%rip), %rsi      # 0xb8ae
movq (%rsp), %rdx
xorl %eax, %eax
callq 0x4a05
callq 0x277a
leaq 0x73f4(%rip), %rdi      # 0xb888
movq %rax, %rsi
xorl %eax, %eax
callq 0x4918
movq 0x8(%r15), %rdi
leaq 0x73bb(%rip), %rsi      # 0xb864
movq %r12, %rdx
jmp 0x4481