// File: /workspace/github_c_makefile_star2_O0/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
movq %rsp, %rbp
subq $0x90, %rsp
movq %rdi, -0x10(%rbp)
movl $0x1, %edi
movl $0x20, %esi
callq 0x10b0
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movl (%rax), %eax
decl %eax
movl %eax, %ecx
movq %rcx, -0x88(%rbp)
subl $0x6, %eax
ja 0x3645
movq -0x88(%rbp), %rax
leaq 0xc1a2(%rip), %rcx      # 0xf48c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x18(%rbp), %rax
movl $0x0, (%rax)
movq -0x18(%rbp), %rax
movl $0x8, 0x4(%rax)
movq -0x18(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x364d
movq -0x18(%rbp), %rax
movl $0x1, (%rax)
movq -0x18(%rbp), %rax
movl $0x1, 0x4(%rax)
movq -0x18(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x364d
movq -0x18(%rbp), %rax
movl $0x2, (%rax)
movq -0x18(%rbp), %rax
movl $0x8, 0x4(%rax)
movq -0x18(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x364d
movq -0x18(%rbp), %rax
movl $0x3, (%rax)
movq -0x18(%rbp), %rax
movl $0x8, 0x4(%rax)
movq -0x18(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x364d
movq -0x18(%rbp), %rax
movl $0x5, (%rax)
movq -0x18(%rbp), %rax
movl $0x0, 0x4(%rax)
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rax
cmpl $0x0, 0x8(%rax)
je 0x35be
movq 0x11d88(%rip), %rdi     # 0x15150
movq -0x28(%rbp), %rsi
callq 0xeb80
movq %rax, %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x18(%rax)
movq -0x18(%rbp), %rax
cmpq $0x0, 0x18(%rax)
jne 0x3443
movl $0x10, %edi
callq 0x10f0
movq %rax, %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x18(%rax)
movl $0x400, %edi            # imm = 0x400
callq 0xe900
movq %rax, %rcx
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rax
movq %rcx, (%rax)
movq -0x30(%rbp), %rax
movl 0x8(%rax), %ecx
shll $0x3, %ecx
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rax
movl %ecx, 0x8(%rax)
movq 0x11d20(%rip), %rdi     # 0x15150
movq -0x28(%rbp), %rsi
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rdx
callq 0xe950
jmp 0x3470
movl $0x400, %edi            # imm = 0x400
callq 0xe900
movq %rax, %rcx
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rax
movq %rcx, (%rax)
movq -0x30(%rbp), %rax
movl 0x8(%rax), %ecx
shll $0x3, %ecx
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rax
movl %ecx, 0x8(%rax)
movl $0x0, -0x34(%rbp)
movl $0x0, -0x38(%rbp)
movl -0x38(%rbp), %eax
movq -0x30(%rbp), %rcx
cmpl 0x8(%rcx), %eax
jge 0x35a0
movq -0x30(%rbp), %rax
movq (%rax), %rax
movslq -0x38(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x48(%rbp)
movq $0x0, -0x50(%rbp)
movl $0x0, -0x54(%rbp)
movl -0x54(%rbp), %eax
movq -0x48(%rbp), %rcx
cmpl 0x8(%rcx), %eax
jge 0x3508
movq -0x48(%rbp), %rax
movq (%rax), %rax
movslq -0x54(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x60(%rbp)
movq -0x60(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x68(%rbp)
cmpq $0x0, -0x68(%rbp)
jne 0x34ee
jmp 0x34fd
movq -0x68(%rbp), %rdi
callq 0x32a0
movq %rax, -0x50(%rbp)
jmp 0x3508
movl -0x54(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x54(%rbp)
jmp 0x34bb
movq -0x40(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x70(%rbp)
cmpq $0x0, -0x70(%rbp)
je 0x3535
movq -0x70(%rbp), %rax
movl (%rax), %ecx
movq -0x50(%rbp), %rax
movl %ecx, 0x10(%rax)
movq -0x50(%rbp), %rax
movl $0x8, 0x8(%rax)
jmp 0x3543
movq -0x50(%rbp), %rax
movl 0x4(%rax), %ecx
movq -0x50(%rbp), %rax
movl %ecx, 0x8(%rax)
movl $0x10, %edi
callq 0x10f0
movq %rax, -0x78(%rbp)
movq -0x50(%rbp), %rcx
movq -0x78(%rbp), %rax
movq %rcx, (%rax)
movl -0x34(%rbp), %ecx
movq -0x78(%rbp), %rax
movl %ecx, 0x8(%rax)
movq -0x78(%rbp), %rax
movq (%rax), %rax
movl 0x8(%rax), %eax
addl -0x34(%rbp), %eax
movl %eax, -0x34(%rbp)
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rax
movq (%rax), %rdi
movq -0x40(%rbp), %rax
movq 0x10(%rax), %rsi
movq -0x78(%rbp), %rdx
callq 0xe950
movl -0x38(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x38(%rbp)
jmp 0x347e
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rax
movq (%rax), %rax
movl 0x8(%rax), %ecx
shll $0x3, %ecx
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rax
movl %ecx, 0x8(%rax)
jmp 0x35c0
jmp 0x35c0
movq -0x18(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x364d
movq -0x18(%rbp), %rax
movl $0x5, (%rax)
movq 0x11b72(%rip), %rdi     # 0x15150
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rsi
callq 0xeb80
movq %rax, -0x80(%rbp)
cmpq $0x0, -0x80(%rbp)
jne 0x3621
movl $0x1, %edi
movl $0x10, %esi
callq 0x10b0
movq %rax, -0x80(%rbp)
movq 0x11b40(%rip), %rdi     # 0x15150
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rsi
movq -0x80(%rbp), %rdx
callq 0xe950
movq -0x80(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x18(%rax)
movq -0x80(%rbp), %rax
movl 0x8(%rax), %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0x4(%rax)
movq -0x18(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x364d
movq $0x0, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x90, %rsp
popq %rbp
retq
nopw (%rax,%rax)