// File: /workspace/github_c_makefile_star2_O3/chgzm[P]minic/generator.c
// Function: process_type_specifier_in_global
static Type* process_type_specifier_in_global(const TypeSpecifierNode* node) {
    Type* type = calloc(1, sizeof(Type));

    switch (node->type_specifier) {
    case TYPE_VOID: { 
        type->base_type = VAR_VOID;
        type->type_size = 8;
        return type;
    }
    case TYPE_CHAR: { 
        type->base_type = VAR_CHAR;
        type->type_size = 1;
        return type;
    }
    case TYPE_INT: {
        type->base_type = VAR_INT;
        type->type_size = 8;
        return type;
    }
    case TYPE_DOUBLE: { 
        type->base_type = VAR_DOUBLE;
        type->type_size = 8;
        return type;
    }
    case TYPE_STRUCT: { 
        type->base_type = VAR_STRUCT;   
        type->type_size = 0;

        const StructSpecifierNode* struct_specifier_node = node->struct_specifier_node;         

        const char* struct_name = struct_specifier_node->identifier;
        const Vector* struct_declaration_nodes = struct_specifier_node->struct_declaration_nodes;
        //
        //  "struct" identifier { {struct-declaration}+ }
        //  
        if (struct_declaration_nodes->size != 0) {
            type->struct_info = strptrmap_get(struct_map, struct_name);
            if (type->struct_info == NULL) { 
                type->struct_info = malloc(sizeof(StructInfo));
                type->struct_info->field_info_map = create_strptrmap(1024);
                type->struct_info->size           = struct_declaration_nodes->size * 8; // @todo
                strptrmap_put(struct_map, struct_name, type->struct_info);
            } else {
                type->struct_info->field_info_map = create_strptrmap(1024);
                type->struct_info->size           = struct_declaration_nodes->size * 8; // @todo
            }

            int offset = 0;
            for (int i = 0; i < struct_declaration_nodes->size; ++i) {
                const StructDeclarationNode* struct_declaration_node  = struct_declaration_nodes->elements[i];
                const Vector* specifier_qualifier_nodes = struct_declaration_node->specifier_qualifier_nodes;

                Type* field_type = NULL;
                for (int j = 0; j < specifier_qualifier_nodes->size; ++j) {
                    const SpecifierQualifierNode* specifier_qualifier_node = specifier_qualifier_nodes->elements[j];
                    const TypeSpecifierNode*      type_specifier_node      = specifier_qualifier_node->type_specifier_node;
                    if (type_specifier_node == NULL) {
                        continue;
                    }

                    field_type = process_type_specifier_in_global(type_specifier_node);
                    break;
                }

                const PointerNode* pointer_node = struct_declaration_node->pointer_node;
                if (pointer_node != NULL) {
                    field_type->ptr_count = pointer_node->count;
                    field_type->size      = 8; 
                } else {
                    field_type->size = field_type->type_size;
                }

                FieldInfo* field_info = malloc(sizeof(FieldInfo));
                field_info->type      = field_type;

                field_info->offset = offset;
                offset += field_info->type->size;

                strptrmap_put(type->struct_info->field_info_map, struct_declaration_node->identifier, field_info);
            }
            type->struct_info->size = type->struct_info->field_info_map->size * 8;
        }
        //
        // "struct" identifier
        //
        else {
            // @todo
        }

        return type;
    }
    case TYPE_TYPEDEFNAME: {
        type->base_type = VAR_STRUCT;   
        StructInfo* struct_info = strptrmap_get(struct_map, node->struct_name);
        if (struct_info == NULL) {
            struct_info = calloc(1, sizeof(StructInfo));
            strptrmap_put(struct_map, node->struct_name, struct_info);
        }
        type->struct_info = struct_info;
        type->type_size   = struct_info->size;
        return type;
    }
    default: {
        return NULL;
    }
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rdi, %r14
movl $0x1, %edi
movl $0x20, %esi
callq 0x10c0
movq %rax, %rbx
movl (%r14), %ecx
xorl %eax, %eax
decl %ecx
cmpl $0x6, %ecx
ja 0x2bac
leaq 0x696a(%rip), %rdx      # 0x948c
movslq (%rdx,%rcx,4), %rcx
addq %rdx, %rcx
jmpq *%rcx
movl $0x8, 0x4(%rbx)
jmp 0x2ba9
movabsq $0x800000002, %rax      # imm = 0x800000002
jmp 0x2ba6
movl $0x5, (%rbx)
movq 0xb5db(%rip), %rdi      # 0xe128
movq 0x10(%r14), %rsi
callq 0x8a1e
movq %rax, %r15
testq %rax, %rax
jne 0x2b83
movl $0x1, %edi
movl $0x10, %esi
callq 0x10c0
movq %rax, %r15
movq 0xb5b1(%rip), %rdi      # 0xe128
movq 0x10(%r14), %rsi
movq %rax, %rdx
callq 0x88ff
movq %r15, 0x18(%rbx)
movl 0x8(%r15), %eax
movl %eax, 0x4(%rbx)
jmp 0x2ba9
movabsq $0x100000001, %rax      # imm = 0x100000001
jmp 0x2ba6
movabsq $0x800000003, %rax      # imm = 0x800000003
movq %rax, (%rbx)
movq %rbx, %rax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl $0x5, (%rbx)
movq 0x8(%r14), %rax
movq 0x8(%rax), %r12
cmpl $0x0, 0x8(%r12)
je 0x2ba9
movq (%rax), %r15
movq 0xb54d(%rip), %rdi      # 0xe128
movq %r15, %rsi
callq 0x8a1e
movq %rax, 0x18(%rbx)
testq %rax, %rax
movq %rbx, 0x8(%rsp)
je 0x2c13
movq %rax, %r14
movl $0x400, %edi            # imm = 0x400
callq 0x88c7
movq %rax, (%r14)
movl 0x8(%r12), %eax
leal (,%rax,8), %ecx
movl %ecx, 0x8(%r14)
jmp 0x2c54
movl $0x10, %edi
callq 0x1100
movq %rax, %r14
movq %rax, 0x18(%rbx)
movl $0x400, %edi            # imm = 0x400
callq 0x88c7
movq %rax, (%r14)
movl 0x8(%r12), %eax
shll $0x3, %eax
movl %eax, 0x8(%r14)
movq 0xb4e4(%rip), %rdi      # 0xe128
movq %r15, %rsi
movq %r14, %rdx
callq 0x88ff
movl 0x8(%r12), %eax
testl %eax, %eax
jle 0x2cfe
xorl %r13d, %r13d
xorl %ebp, %ebp
movq %r12, 0x10(%rsp)
movq (%r12), %rax
movq (%rax,%r13,8), %rbx
movq (%rbx), %rcx
movslq 0x8(%rcx), %rax
testq %rax, %rax
jle 0x2c93
movq (%rcx), %rcx
xorl %edx, %edx
movq (%rcx,%rdx,8), %rsi
movq (%rsi), %rdi
testq %rdi, %rdi
jne 0x2c98
incq %rdx
cmpq %rdx, %rax
jne 0x2c7f
xorl %r15d, %r15d
jmp 0x2ca0
callq 0x2ae8
movq %rax, %r15
movq %r14, %r12
movq 0x8(%rbx), %rax
testq %rax, %rax
je 0x2cba
movl (%rax), %eax
movl %eax, 0x10(%r15)
movl $0x8, %r14d
jmp 0x2cbe
movl 0x4(%r15), %r14d
movl %r14d, 0x8(%r15)
movl $0x10, %edi
callq 0x1100
movq %r15, (%rax)
movl %ebp, 0x8(%rax)
addl %r14d, %ebp
movq %r12, %r14
movq (%r12), %rdi
movq 0x10(%rbx), %rsi
movq %rax, %rdx
callq 0x88ff
incq %r13
movq 0x10(%rsp), %r12
movslq 0x8(%r12), %rax
cmpq %rax, %r13
jl 0x2c66
movq (%r14), %rax
movl 0x8(%rax), %eax
shll $0x3, %eax
movl %eax, 0x8(%r14)
movq 0x8(%rsp), %rax
jmp 0x2bac