// File: /workspace/github_c_makefile_star2_O3/aquaxis[P]synverll/src/parser_ir.c
// Function: create_stage_parser_tree
int create_stage_parser_tree()
{
	PARSER_TREE_IR *now_parser_tree_ir;
    char *token;
	int current_parallel = 0;
	int current_stage = 0;
	int new_stage = 0;
	INST_STAGE inst_stage;
	INST_STAGE proc_stage;
    char *line_buf;
    char *init_name, *next_name;

	token = calloc(STR_MAX, 1);
	init_name = calloc(STR_MAX, 1);
	next_name = calloc(STR_MAX, 1);

    printf(" -> Create Stage for LLVM-IR\n");
    now_parser_tree_ir = parser_tree_ir_top;
    while(now_parser_tree_ir != NULL){

		if( current_stage == 0 ){
			if( now_parser_tree_ir->flag == PARSER_IR_FLAG_MODULE ){
				/*
				 * モジュール宣言に入った時にステージが初めてスタートします。
				 */
				current_stage = 1;
				current_parallel = 0;
			}
			now_parser_tree_ir->parallel = current_parallel;
			now_parser_tree_ir->stage = current_stage;
		}else{
			switch(now_parser_tree_ir->flag){
				case PARSER_IR_FLAG_MODULE:
//					printf("[ERROR] Stage Level for Module Start : parser_tree_1st_stage().\n");
					break;
				case PARSER_IR_FLAG_REGISTER:
				case PARSER_IR_FLAG_FLOAT:
					inst_stage = search_reg_llvm(now_parser_tree_ir, now_parser_tree_ir->label, now_parser_tree_ir->reg.input_left, now_parser_tree_ir->reg.input_right);
					if((current_parallel > inst_stage.parallel) || (current_stage > inst_stage.stage)){
						current_parallel++;
					}
					current_stage = inst_stage.stage;
					current_stage++;
					now_parser_tree_ir->parallel = current_parallel;
					now_parser_tree_ir->stage = current_stage;
					now_parser_tree_ir->prev_parallel = inst_stage.parallel;
					now_parser_tree_ir->prev_stage = inst_stage.stage;
					break;
				case PARSER_IR_FLAG_WIRE:
					/* WIREはstageに左右されない */
					inst_stage = search_reg_llvm(now_parser_tree_ir, now_parser_tree_ir->label, now_parser_tree_ir->reg.input_left, now_parser_tree_ir->reg.input_right);
					if((current_parallel > inst_stage.parallel) || (current_stage > inst_stage.stage)){
						current_parallel++;
					}
					current_stage = inst_stage.stage;
					now_parser_tree_ir->parallel = current_parallel;
					now_parser_tree_ir->stage = current_stage;
					now_parser_tree_ir->prev_parallel = inst_stage.parallel;
					now_parser_tree_ir->prev_stage = inst_stage.stage;
					break;
				case PARSER_IR_FLAG_CALL:
				case PARSER_IR_FLAG_SCALL:
					inst_stage = search_args_llvm(now_parser_tree_ir, now_parser_tree_ir->label, now_parser_tree_ir->call.argument);
					if((current_parallel > inst_stage.parallel) || (current_stage > inst_stage.stage)){
						current_parallel++;
					}

					proc_stage = search_proc_llvm(now_parser_tree_ir, now_parser_tree_ir->flag);

					if(inst_stage.stage >= proc_stage.stage){
							current_stage = inst_stage.stage;
					}else{
							current_stage = proc_stage.stage;
					}
					current_parallel = proc_stage.parallel;

					current_stage++;
					now_parser_tree_ir->parallel = current_parallel;
					now_parser_tree_ir->stage = current_stage;
					now_parser_tree_ir->prev_parallel = inst_stage.parallel;
					now_parser_tree_ir->prev_stage = inst_stage.stage;
					break;
				case PARSER_IR_FLAG_REGISTER_LOOP:
					line_buf = charalloc(now_parser_tree_ir->phi.argument);

					do{
						//
						get_token_llvm(line_buf, token);
						// value
						get_token_llvm(line_buf, token);
//						printf("[LOOP]: value: %s\n", token);

						if(is_register_name(token)){
							inst_stage = search_reg_llvm(now_parser_tree_ir, now_parser_tree_ir->label, token, "");
							if((current_parallel > inst_stage.parallel) || (current_stage > inst_stage.stage)){
								current_parallel++;
							}
						}
						proc_stage = search_proc_llvm(now_parser_tree_ir, now_parser_tree_ir->flag);

						if(inst_stage.stage >= proc_stage.stage){
								current_stage = inst_stage.stage;
						}else{
								current_stage = proc_stage.stage;
						}
						current_parallel = proc_stage.parallel;

						// ,
						get_token_llvm(line_buf, token);
						// name
						get_token_llvm(line_buf, token);
//						printf("[LOOP]: name: %s\n", token);
						// ]
						get_token_llvm(line_buf, token);
						// ,
						get_token_llvm(line_buf, token);
					}while(strlen(line_buf) > 0);
					free(line_buf);
					current_stage++;
					now_parser_tree_ir->parallel = current_parallel;
					now_parser_tree_ir->stage = current_stage;
					now_parser_tree_ir->prev_parallel = inst_stage.parallel;
					now_parser_tree_ir->prev_stage = inst_stage.stage;
					break;
				case PARSER_IR_FLAG_STORE:
					/*  */
					inst_stage = search_reg_llvm(now_parser_tree_ir, now_parser_tree_ir->label, now_parser_tree_ir->reg.input_left, now_parser_tree_ir->reg.input_right);
					if((current_parallel > inst_stage.parallel) || (current_stage > inst_stage.stage)){
						current_parallel++;
					}
					proc_stage = search_proc_llvm(now_parser_tree_ir, now_parser_tree_ir->flag);

					if(inst_stage.stage >= proc_stage.stage){
							current_stage = inst_stage.stage;
					}else{
							current_stage = proc_stage.stage;
					}
					current_parallel = proc_stage.parallel;

					current_stage++;
					now_parser_tree_ir->parallel = current_parallel;
					now_parser_tree_ir->stage = current_stage;
					now_parser_tree_ir->prev_parallel = inst_stage.parallel;
					now_parser_tree_ir->prev_stage = inst_stage.stage;
					break;
				case PARSER_IR_FLAG_COMPARE:
					inst_stage = search_reg_llvm(now_parser_tree_ir, now_parser_tree_ir->label, now_parser_tree_ir->comp.input_left, now_parser_tree_ir->comp.input_right);
					if((current_parallel > inst_stage.parallel) || (current_stage > inst_stage.stage)){
						current_parallel++;
					}
					current_stage = inst_stage.stage;
					current_stage++;
					now_parser_tree_ir->parallel = current_parallel;
					now_parser_tree_ir->stage = current_stage;
					now_parser_tree_ir->prev_parallel = inst_stage.parallel;
					now_parser_tree_ir->prev_stage = inst_stage.stage;
					break;
				case PARSER_IR_FLAG_POINTER:
					inst_stage = search_reg_llvm(now_parser_tree_ir, now_parser_tree_ir->label, now_parser_tree_ir->pointer.name, now_parser_tree_ir->pointer.init_name);
					// ポインターが階層になっている場合は、全ての位置を把握する必要がある
					line_buf = charalloc(now_parser_tree_ir->pointer.add_name);

					do{
						// タイプ
						get_irtype_llvm(line_buf, token);
						// 変数
						get_irtype_llvm(line_buf, token);
						proc_stage = search_reg_llvm(now_parser_tree_ir, now_parser_tree_ir->label, token, "");
						// ,
						get_token_llvm(line_buf, token);
						if(proc_stage.stage > new_stage){
//							new_parallel = proc_stage.parallel;
							new_stage = proc_stage.stage;
						}
					}while(!strcmp(token, ",") && (strlen(line_buf) > 0));

					free(line_buf);

					if(inst_stage.stage >= proc_stage.stage){
							current_stage = inst_stage.stage;
					}else{
							current_stage = proc_stage.stage;
					}
					current_parallel = proc_stage.parallel;

					current_stage++;
					now_parser_tree_ir->parallel = current_parallel;
					now_parser_tree_ir->stage = current_stage;
					now_parser_tree_ir->prev_parallel = inst_stage.parallel;
					now_parser_tree_ir->prev_stage = inst_stage.stage;
					break;
				case PARSER_IR_FLAG_LOAD:
					line_buf = charalloc(now_parser_tree_ir->load.name);

					// getelementptr
					get_token_llvm(line_buf, token);
					if(!strcmp(token, "getelementptr")){
						// inbounds
						get_token_llvm(line_buf, token);

						inst_stage = search_args_llvm(now_parser_tree_ir, now_parser_tree_ir->label, line_buf);
						if((current_parallel > inst_stage.parallel) || (current_stage > inst_stage.stage)){
							current_parallel++;
						}
					}else{
						inst_stage = search_reg_llvm(now_parser_tree_ir, now_parser_tree_ir->label, token, "");
					}
					free(line_buf);
					proc_stage = search_proc_llvm(now_parser_tree_ir, now_parser_tree_ir->flag);

					if(inst_stage.stage >= proc_stage.stage){
							current_stage = inst_stage.stage;
					}else{
							current_stage = proc_stage.stage;
					}
					current_parallel = proc_stage.parallel;

					current_stage++;
					now_parser_tree_ir->parallel = current_parallel;
					now_parser_tree_ir->stage = current_stage;
					now_parser_tree_ir->prev_parallel = inst_stage.parallel;
					now_parser_tree_ir->prev_stage = inst_stage.stage;
					break;
				case PARSER_IR_FLAG_SELECT:
					inst_stage = search_reg_llvm(now_parser_tree_ir, now_parser_tree_ir->label, now_parser_tree_ir->select.condition_value, "");
					if((current_parallel > inst_stage.parallel) || (current_stage > inst_stage.stage)){
						current_parallel++;
					}
					current_stage = inst_stage.stage;
					current_stage++;
					now_parser_tree_ir->parallel = current_parallel;
					now_parser_tree_ir->stage = current_stage;
					now_parser_tree_ir->prev_parallel = inst_stage.parallel;
					now_parser_tree_ir->prev_stage = inst_stage.stage;
					break;
				case PARSER_IR_FLAG_LABEL:
					inst_stage = search_maxstage_llvm(now_parser_tree_ir);
					current_stage = inst_stage.stage;
					current_stage++;
					now_parser_tree_ir->parallel = current_parallel;
					now_parser_tree_ir->stage = current_stage;
					now_parser_tree_ir->prev_parallel = inst_stage.parallel;
					now_parser_tree_ir->prev_stage = inst_stage.stage;
					break;
				case PARSER_IR_FLAG_BRANCH:
					inst_stage = search_reg_llvm(now_parser_tree_ir, now_parser_tree_ir->label, now_parser_tree_ir->branch.condition_value, "");
					if((current_parallel > inst_stage.parallel) || (current_stage > inst_stage.stage)){
						current_parallel++;
					}
					proc_stage = search_proc_llvm(now_parser_tree_ir, now_parser_tree_ir->flag);

					if(inst_stage.stage >= proc_stage.stage){
							current_stage = inst_stage.stage;
					}else{
							current_stage = proc_stage.stage;
					}
					current_parallel = proc_stage.parallel;

					current_stage++;
					now_parser_tree_ir->parallel = current_parallel;
					now_parser_tree_ir->stage = current_stage;
					now_parser_tree_ir->prev_parallel = inst_stage.parallel;
					now_parser_tree_ir->prev_stage = inst_stage.stage;
					break;
				case PARSER_IR_FLAG_TYPE:
				case PARSER_IR_FLAG_ARRAY:
				case PARSER_IR_FLAG_RETURN:
				case PARSER_IR_FLAG_ALLOCA:
				case PARSER_IR_FLAG_CLOSE:
					now_parser_tree_ir->prev_parallel = current_parallel;
					now_parser_tree_ir->prev_stage = current_stage;
					current_stage++;
					now_parser_tree_ir->parallel = current_parallel;
					now_parser_tree_ir->stage = current_stage;
					break;
				case PARSER_IR_FLAG_NONE:
				case PARSER_IR_FLAG_UNKNOWN:
					break;
				default:
					printf("Unknown(can't parser: %d)\n", now_parser_tree_ir->flag);
					break;
			}

		}
        now_parser_tree_ir = now_parser_tree_ir->next_ptr;
    }

    free(token);
    free(init_name);
    free(next_name);

    return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movl $0x400, %edi            # imm = 0x400
movl $0x1, %esi
callq 0x10f0
movq %rax, %rbx
leaq 0x9b1f(%rip), %rdi      # 0xe5ea
callq 0x1070
movq 0xf659(%rip), %r14      # 0x14130
testq %r14, %r14
je 0x4fb0
xorl %r13d, %r13d
xorl %r12d, %r12d
xorl %ebp, %ebp
movl 0x10(%r14), %esi
testl %ebp, %ebp
je 0x4b17
cmpl $0x14, %esi
ja 0x4cee
movl %esi, %eax
leaq 0x964a(%rip), %rcx      # 0xe14c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl %r12d, 0x20(%r14)
movl %ebp, 0x24(%r14)
incl %ebp
jmp 0x4b24
xorl %ebp, %ebp
cmpl $0xf, %esi
sete %bpl
cmovel %r13d, %r12d
movl %r12d, 0x18(%r14)
movl %ebp, 0x1c(%r14)
jmp 0x4f9c
leaq 0x2430(%r14), %rdx
movq %r14, %rdi
callq 0x4962
movq %rax, %r15
movq %rax, %rdi
shrq $0x20, %r15
movq 0xf5df(%rip), %rcx      # 0x14130
movq %r14, %rax
movl $0x94120, %esi          # imm = 0x94120
movq (%rax), %rax
cmpq %rcx, %rax
je 0x4f03
movl 0x10(%rax), %edx
cmpl $0x13, %edx
ja 0x4b59
btl %edx, %esi
jae 0x4b59
jmp 0x4cca
leaq 0x3034(%r14), %rdx
leaq 0x3834(%r14), %rcx
jmp 0x4b95
leaq 0xa434(%r14), %rdx
leaq 0xac34(%r14), %rcx
movq %r14, %rdi
jmp 0x4c43
leaq 0x7834(%r14), %rdi
callq 0x137c
movq %rax, %r13
movq %rax, %rdi
movq %rbx, %rsi
callq 0xcaa7
movq %rbx, %rdi
leaq 0x95e9(%rip), %rsi      # 0xe1aa
callq 0x1100
testl %eax, %eax
je 0x4f24
movq %r14, %rdi
movq %rbx, %rdx
leaq 0xb3e8(%rip), %rcx      # 0xffc3
callq 0x484f
jmp 0x4f3a
leaq 0x3034(%r14), %rdx
leaq 0x3834(%r14), %rcx
movq %r14, %rdi
callq 0x484f
movq %rax, %r15
movq %rax, %rdi
shrq $0x20, %r15
movq 0xf524(%rip), %rcx      # 0x14130
movq %r14, %rax
movl $0x94120, %esi          # imm = 0x94120
movq (%rax), %rax
cmpq %rcx, %rax
je 0x4f03
movl 0x10(%rax), %edx
cmpl $0x13, %edx
ja 0x4c14
btl %edx, %esi
jae 0x4c14
jmp 0x4cca
leaq 0x5834(%r14), %rdx
movq %r14, %rdi
leaq 0xb380(%rip), %rcx      # 0xffc3
callq 0x484f
movq %rax, %rdx
movq %rax, %r15
shrq $0x20, %r15
cmpl %edx, %r12d
setg %al
cmpl %r15d, %ebp
setg %cl
orb %al, %cl
movzbl %cl, %eax
addl %r12d, %eax
leal 0x1(%r15), %ebp
movl %eax, 0x18(%r14)
movl %ebp, 0x1c(%r14)
movl %edx, 0x20(%r14)
movl %r15d, 0x24(%r14)
movl %eax, %r12d
jmp 0x4f9c
leaq 0x4834(%r14), %rdx
movq %r14, %rdi
leaq 0xb330(%rip), %rcx      # 0xffc3
callq 0x484f
movq %rax, %r15
movq %rax, %rdi
shrq $0x20, %r15
movq 0xf487(%rip), %rcx      # 0x14130
movq %r14, %rax
movl $0x94120, %esi          # imm = 0x94120
movq (%rax), %rax
cmpq %rcx, %rax
je 0x4f03
movl 0x10(%rax), %edx
cmpl $0x13, %edx
ja 0x4cb1
btl %edx, %esi
jae 0x4cb1
movq 0x18(%rax), %r12
movq %r12, %rbp
shrq $0x20, %rbp
cmpl %ebp, %r15d
cmovgl %r15d, %ebp
incl %ebp
movl %r12d, 0x18(%r14)
movl %ebp, 0x1c(%r14)
movq %rdi, %rdx
jmp 0x4f94
leaq 0xa919(%rip), %rdi      # 0xf60e
xorl %eax, %eax
movq %rdx, %r13
callq 0x10b0
movq %r13, %rdx
jmp 0x4efb
movq %rdx, (%rsp)
leaq 0xb434(%r14), %rdi
callq 0x137c
movq %rax, %r13
movl $0x94120, %ebp          # imm = 0x94120
movq %r13, %rdi
movq %rbx, %rsi
callq 0xcaa7
movq %r13, %rdi
movq %rbx, %rsi
callq 0xcaa7
movq %rbx, %rdi
callq 0x4fc9
testl %eax, %eax
je 0x4d5e
movq %r14, %rdi
movq %rbx, %rdx
leaq 0xb275(%rip), %rcx      # 0xffc3
callq 0x484f
movq %rax, %r15
movq %rax, (%rsp)
shrq $0x20, %r15
movq 0xf3cb(%rip), %rcx      # 0x14130
movq %r14, %rax
movq (%rax), %rax
cmpq %rcx, %rax
je 0x4dba
movl 0x10(%rax), %edx
cmpl $0x13, %edx
ja 0x4d68
btl %edx, %ebp
jae 0x4d68
movq 0x18(%rax), %r12
movq %r13, %rdi
movq %rbx, %rsi
callq 0xcaa7
movq %r13, %rdi
movq %rbx, %rsi
callq 0xcaa7
movq %r13, %rdi
movq %rbx, %rsi
callq 0xcaa7
movq %r13, %rdi
movq %rbx, %rsi
callq 0xcaa7
cmpb $0x0, (%r13)
jne 0x4d1f
jmp 0x4dbf
xorl %r12d, %r12d
jmp 0x4d81
movq %r12, %rbp
shrq $0x20, %rbp
cmpl %ebp, %r15d
cmovgl %r15d, %ebp
movq %r13, %rdi
callq 0x1030
jmp 0x4ee5
movq 0xf34f(%rip), %rax      # 0x14130
movq %r14, %rcx
movq (%rcx), %rcx
xorl %edx, %edx
cmpq %rax, %rcx
je 0x4f0b
movl 0x1c(%rcx), %r15d
testl %r15d, %r15d
jle 0x4de4
jmp 0x4f0e
leaq 0x3034(%r14), %rdx
leaq 0x3834(%r14), %rcx
movq %r14, %rdi
callq 0x484f
movq %rax, %rdx
movq %rax, %r15
shrq $0x20, %r15
cmpl %edx, %r12d
setg %al
cmpl %r15d, %ebp
setg %cl
orb %al, %cl
movzbl %cl, %eax
addl %r12d, %eax
movl %eax, 0x18(%r14)
movl %r15d, 0x1c(%r14)
movl %edx, 0x20(%r14)
movl %r15d, 0x24(%r14)
movl %r15d, %ebp
jmp 0x4c7a
leaq 0x8434(%r14), %rdx
leaq 0x8c34(%r14), %rcx
movq %r14, %rdi
callq 0x484f
movq %rax, %r15
movq %rax, (%rsp)
shrq $0x20, %r15
leaq 0x9434(%r14), %rdi
callq 0x137c
movq %rax, %r13
leaq 0xac0d(%rip), %rbp      # 0xfa90
movq %r13, %rdi
movq %rbx, %rsi
callq 0x1fbb
movq %r13, %rdi
movq %rbx, %rsi
callq 0x1fbb
movq %r14, %rdi
movq %rbx, %rdx
leaq 0xb11d(%rip), %rcx      # 0xffc3
callq 0x484f
movq %rax, %r12
movq %r13, %rdi
movq %rbx, %rsi
callq 0xcaa7
movq %rbx, %rdi
movq %rbp, %rsi
callq 0x1100
testl %eax, %eax
jne 0x4ecf
cmpb $0x0, (%r13)
jne 0x4e83
movq %r12, %rbp
shrq $0x20, %rbp
movq %r13, %rdi
callq 0x1030
cmpl %ebp, %r15d
cmovgl %r15d, %ebp
incl %ebp
movl %r12d, 0x18(%r14)
movl %ebp, 0x1c(%r14)
movq (%rsp), %rdx
movl %edx, 0x20(%r14)
movl %r15d, 0x24(%r14)
xorl %r13d, %r13d
jmp 0x4f9c
xorl %r12d, %r12d
jmp 0x4cce
xorl %r15d, %r15d
leal 0x1(%r15), %ebp
movl %r12d, 0x18(%r14)
movl %ebp, 0x1c(%r14)
movl $0x0, 0x20(%r14)
jmp 0x4f98
movq %r13, %rdi
movq %rbx, %rsi
callq 0xcaa7
movq %r14, %rdi
movq %r13, %rdx
callq 0x4962
movq %rax, %r15
movl $0x94120, %ebp          # imm = 0x94120
movq %rax, (%rsp)
shrq $0x20, %r15
movq %r13, %rdi
callq 0x1030
movq 0xf1d7(%rip), %rcx      # 0x14130
movq %r14, %rax
xorl %r13d, %r13d
movq (%rax), %rax
cmpq %rcx, %rax
je 0x4fab
movl 0x10(%rax), %edx
cmpl $0x13, %edx
ja 0x4f5f
btl %edx, %ebp
jae 0x4f5f
movq 0x18(%rax), %r12
movq %r12, %rbp
shrq $0x20, %rbp
cmpl %ebp, %r15d
cmovgl %r15d, %ebp
incl %ebp
movl %r12d, 0x18(%r14)
movl %ebp, 0x1c(%r14)
movq (%rsp), %rdx
movl %edx, 0x20(%r14)
movl %r15d, 0x24(%r14)
movq 0x8(%r14), %r14
testq %r14, %r14
jne 0x4ae8
jmp 0x4fb0
xorl %r12d, %r12d
jmp 0x4f78
movq %rbx, %rdi
callq 0x1030
xorl %eax, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq