// File: /workspace/github_c_makefile_star2_O2/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
pushq $0x1
popq %rdi
pushq $0x20
popq %rsi
callq 0x10c0
movq %rax, %rbx
movl (%r14), %ecx
xorl %eax, %eax
decl %ecx
cmpl $0x6, %ecx
ja 0x292f
leaq 0x6be3(%rip), %rdx      # 0x948c
movslq (%rdx,%rcx,4), %rcx
addq %rdx, %rcx
jmpq *%rcx
movl $0x8, 0x4(%rbx)
jmp 0x292c
movabsq $0x800000002, %rax      # imm = 0x800000002
jmp 0x2929
movl $0x5, (%rbx)
movq 0xb854(%rip), %rdi      # 0xe128
movq 0x10(%r14), %rsi
callq 0x8412
movq %rax, %r15
testq %rax, %rax
jne 0x2906
pushq $0x1
popq %rdi
pushq $0x10
popq %rsi
callq 0x10c0
movq %rax, %r15
movq 0xb82e(%rip), %rdi      # 0xe128
movq 0x10(%r14), %rsi
movq %rax, %rdx
callq 0x8315
movq %r15, 0x18(%rbx)
movl 0x8(%r15), %eax
movl %eax, 0x4(%rbx)
jmp 0x292c
movabsq $0x100000001, %rax      # imm = 0x100000001
jmp 0x2929
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 0x292c
movq (%rax), %r15
movq 0xb7ca(%rip), %rdi      # 0xe128
movq %r15, %rsi
callq 0x8412
movq %rax, 0x18(%rbx)
testq %rax, %rax
movq %rbx, 0x8(%rsp)
je 0x2993
movq %rax, %r13
movl $0x400, %edi            # imm = 0x400
callq 0x82e4
movq %rax, (%r13)
movl 0x8(%r12), %eax
shll $0x3, %eax
movl %eax, 0x8(%r13)
jmp 0x29ce
pushq $0x10
popq %rdi
callq 0x1100
movq %rax, %r13
movq %rax, 0x18(%rbx)
movl $0x400, %edi            # imm = 0x400
callq 0x82e4
movq %rax, (%r13)
movl 0x8(%r12), %eax
shll $0x3, %eax
movl %eax, 0x8(%r13)
movq 0xb765(%rip), %rdi      # 0xe128
movq %r15, %rsi
movq %r13, %rdx
callq 0x8315
xorl %ebp, %ebp
xorl %ebx, %ebx
movq %r12, 0x10(%rsp)
movslq 0x8(%r12), %rax
cmpq %rax, %rbp
jge 0x2a71
movq (%r12), %rax
movq (%rax,%rbp,8), %r15
movq (%r15), %rax
movl 0x8(%rax), %ecx
testl %ecx, %ecx
movl $0x0, %edx
cmovlel %edx, %ecx
xorl %edx, %edx
cmpq %rdx, %rcx
je 0x2a20
movq (%rax), %rsi
movq (%rsi,%rdx,8), %rsi
movq (%rsi), %rdi
incq %rdx
testq %rdi, %rdi
je 0x29ff
callq 0x2873
movq %rax, %r12
jmp 0x2a23
xorl %r12d, %r12d
movq 0x8(%r15), %rax
testq %rax, %rax
je 0x2a39
movl (%rax), %eax
movl %eax, 0x10(%r12)
pushq $0x8
popq %r14
jmp 0x2a3e
movl 0x4(%r12), %r14d
movl %r14d, 0x8(%r12)
pushq $0x10
popq %rdi
callq 0x1100
movq %r12, (%rax)
movl %ebx, 0x8(%rax)
addl %r14d, %ebx
movq (%r13), %rdi
movq 0x10(%r15), %rsi
movq %rax, %rdx
callq 0x8315
incq %rbp
movq 0x10(%rsp), %r12
jmp 0x29d7
movq (%r13), %rax
movl 0x8(%rax), %eax
shll $0x3, %eax
movl %eax, 0x8(%r13)
movq 0x8(%rsp), %rax
jmp 0x292f