// File: /workspace/github_c_makefile_star2_O1/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), %r14
movq %r14, %rsi
callq 0x2805
cmpq $0x0, (%r14)
je 0x4a35
movq %rax, %rbp
xorl %ebx, %ebx
movq %rax, 0x8(%rsp)
movq (%rbp,%rbx,8), %r14
movl (%r14), %edi
cmpl $0x421f, %edi           # imm = 0x421F
jg 0x489b
leal -0x4000(%rdi), %eax
cmpl $0x3, %eax
ja 0x4993
leaq 0x8dce(%rip), %rcx      # 0xd658
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
xorl %r15d, %r15d
movq %r14, %r12
jmp 0x48cc
cmpl $0x4220, %edi           # imm = 0x4220
je 0x48bc
cmpl $0x4502, %edi           # imm = 0x4502
jne 0x4a67
movq %r14, %rdi
callq 0x4835
jmp 0x4a27
movq %r14, %rdi
xorl %esi, %esi
callq 0x27c8
movq %rax, %r12
movb $0x1, %r15b
movq %r12, %rdi
xorl %esi, %esi
callq 0x27c8
movq %rax, %rdi
callq 0x26d0
movq %rax, %rsi
leaq 0xf4f8(%rip), %rax      # 0x13de0
movq (%rax), %rdi
movq %rsi, (%rsp)
callq 0xb310
movq %rax, %r13
testq %rax, %rax
je 0x495e
cmpl $0x1, (%r13)
jne 0x4a44
cmpl $0x4000, (%r12)         # imm = 0x4000
jne 0x4a44
testb %r15b, %r15b
je 0x4925
cmpb $0x1, 0x20(%r13)
je 0x4a44
movl $0x1, %esi
movq %r12, %rdi
callq 0x27c8
movq %rax, %rdi
callq 0xbc78
movq %rax, %rbp
movq 0x18(%r13), %rsi
movq %rax, %rdi
callq 0xc0c3
testb %al, %al
je 0x4a51
movq %rbp, %rdi
callq 0xc27a
movq 0x8(%rsp), %rbp
movq %r12, %rdi
callq 0xb58c
testb %r15b, %r15b
je 0x496f
movb $0x1, 0x20(%rax)
testq %r13, %r13
jne 0x4a27
leaq 0xf461(%rip), %rcx      # 0x13de0
movq (%rcx), %rdi
movq (%rsp), %rsi
movq %rax, %rdx
callq 0xb2ff
jmp 0x4a27
cmpl $0x7, %edi
je 0x4a27
jmp 0x4a67
movq %r14, %rdi
xorl %esi, %esi
callq 0x27c8
movq %rax, %rdi
callq 0x26d0
movq %rax, %r15
leaq 0xf423(%rip), %rbp      # 0x13de0
movq (%rbp), %rdi
movq %rax, %rsi
callq 0xb387
movq %rax, %r12
movl $0x1, %esi
movq %r14, %rdi
callq 0x27c8
movq %rax, %r13
movq (%rbp), %rbp
movq %r14, %rdi
callq 0xb58c
movq %rbp, %rdi
movq 0x8(%rsp), %rbp
movq %r15, %rsi
movq %rax, %rdx
callq 0xb307
testq %r13, %r13
je 0x4a27
movq %r13, %rdi
callq 0xbc78
movq %rax, %r13
testq %r12, %r12
je 0x4a1f
movq %r12, %rdi
movq %r13, %rsi
callq 0xc0c3
testb %al, %al
je 0x4a7d
movq %r13, %rdi
callq 0xc27a
incq %rbx
cmpq 0x10(%rsp), %rbx
jb 0x4864
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x8(%r14), %rdi
leaq 0x8e4f(%rip), %rsi      # 0xd89e
jmp 0x4a5c
movq 0x8(%r14), %rdi
leaq 0x8e52(%rip), %rsi      # 0xd8ae
movq (%rsp), %rdx
xorl %eax, %eax
callq 0x5011
callq 0x2874
leaq 0x8e15(%rip), %rdi      # 0xd888
movq %rax, %rsi
xorl %eax, %eax
callq 0x4f1c
movq 0x8(%r14), %rdi
leaq 0x8ddc(%rip), %rsi      # 0xd864
movq %r15, %rdx
jmp 0x4a60