// File: /workspace/github_c_makefile_star2_O1/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, %r12
movl (%r14), %ecx
xorl %eax, %eax
decl %ecx
cmpl $0x6, %ecx
ja 0x2b28
leaq 0x79f7(%rip), %rdx      # 0xa48c
movslq (%rdx,%rcx,4), %rcx
addq %rdx, %rcx
jmpq *%rcx
movabsq $0x800000000, %rax      # imm = 0x800000000
jmp 0x2b21
movabsq $0x800000002, %rax      # imm = 0x800000002
jmp 0x2b21
movl $0x5, (%r12)
movq 0xc663(%rip), %rdi      # 0xf128
movq 0x10(%r14), %rsi
callq 0x8def
movq %rax, %r15
testq %rax, %rax
jne 0x2afb
movl $0x1, %edi
movl $0x10, %esi
callq 0x10c0
movq %rax, %r15
movq 0xc639(%rip), %rdi      # 0xf128
movq 0x10(%r14), %rsi
movq %rax, %rdx
callq 0x8ccb
movq %r15, 0x18(%r12)
movl 0x8(%r15), %eax
movl %eax, 0x4(%r12)
jmp 0x2b25
movabsq $0x100000001, %rax      # imm = 0x100000001
jmp 0x2b21
movabsq $0x800000003, %rax      # imm = 0x800000003
movq %rax, (%r12)
movq %r12, %rax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq $0x5, (%r12)
movq 0x8(%r14), %rax
movq 0x8(%rax), %rbx
cmpl $0x0, 0x8(%rbx)
je 0x2b25
movq (%rax), %r14
movq 0xc5d1(%rip), %rdi      # 0xf128
movq %r14, %rsi
callq 0x8def
movq %rax, 0x18(%r12)
testq %rax, %rax
je 0x2b85
movq %rax, %r15
movl $0x400, %edi            # imm = 0x400
callq 0x8c93
movq %rax, (%r15)
movl 0x8(%rbx), %eax
shll $0x3, %eax
movl %eax, 0x8(%r15)
jmp 0x2bc0
movl $0x10, %edi
callq 0x1100
movq %rax, %r15
movq %rax, 0x18(%r12)
movl $0x400, %edi            # imm = 0x400
callq 0x8c93
movq %rax, (%r15)
movl 0x8(%rbx), %eax
shll $0x3, %eax
movl %eax, 0x8(%r15)
movq 0xc573(%rip), %rdi      # 0xf128
movq %r14, %rsi
movq %r15, %rdx
callq 0x8ccb
cmpl $0x0, 0x8(%rbx)
jle 0x2c88
xorl %r13d, %r13d
xorl %ebp, %ebp
movq %r12, (%rsp)
movq %rbx, 0x8(%rsp)
movq (%rbx), %rax
movq (%rax,%r13,8), %rax
movq %rax, 0x10(%rsp)
movq (%rax), %r12
cmpl $0x0, 0x8(%r12)
jle 0x2c23
xorl %ebx, %ebx
xorl %r14d, %r14d
movq (%r12), %rax
movq (%rax,%rbx,8), %rax
movq (%rax), %r15
testq %r15, %r15
je 0x2c0f
movq %r15, %rdi
callq 0x2a5b
movq %rax, %r14
testq %r15, %r15
jne 0x2c26
incq %rbx
movslq 0x8(%r12), %rax
cmpq %rax, %rbx
jl 0x2bf4
jmp 0x2c26
xorl %r14d, %r14d
movq 0x10(%rsp), %r15
movq 0x8(%r15), %rax
testq %rax, %rax
je 0x2c41
movl (%rax), %eax
movl %eax, 0x10(%r14)
movl $0x8, %ebx
jmp 0x2c45
movl 0x4(%r14), %ebx
movq (%rsp), %r12
movl %ebx, 0x8(%r14)
movl $0x10, %edi
callq 0x1100
movq %r14, (%rax)
movl %ebp, 0x8(%rax)
addl %ebx, %ebp
movq 0x18(%r12), %rcx
movq (%rcx), %rdi
movq 0x10(%r15), %rsi
movq %rax, %rdx
callq 0x8ccb
incq %r13
movq 0x8(%rsp), %rbx
movslq 0x8(%rbx), %rax
cmpq %rax, %r13
jl 0x2bd8
movq 0x18(%r12), %rax
movq (%rax), %rcx
movl 0x8(%rcx), %ecx
shll $0x3, %ecx
movl %ecx, 0x8(%rax)
jmp 0x2b25