/* Shiltiumcomp -- the first Shiltolang compiler Copyright (C) 2010 Gregory Cohen This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "../../global_headers/headers.h" #include "instructions/x86_instructions.h" #include "../../global_headers/globals.h" /* Get the length of the instructions generated by store_float_variable_on_stack() */ static u get_length_of_instructions_generated_by_store_float_variable_on_stack(const Variable* cr variable) { u variable_stack_offset; assert_comparison(variable, !=, NULL, const Variable*, void*); variable_stack_offset = ARROW(variable, stack_offset); #if SIXTY_FOUR_BIT if (variable_stack_offset) { if (variable_stack_offset <= 127) { return dac_get_length_of_fstp_deref_register_as_qword_plus_signed_byte_offset(REGISTER_RSP); } else { return dac_get_length_of_mov_reg64_lit64(REGISTER_R11, variable_stack_offset) + dac_get_length_of_add_reg64_reg64() + dac_get_length_of_fstp_deref_register_as_qword(REGISTER_R11); } } else { return dac_get_length_of_fstp_deref_register_as_qword(REGISTER_RSP); } #else if (!variable_stack_offset) { return dac_get_length_of_fstp_deref_register_as_qword(REGISTER_ESP); } return dac_get_length_of_mov_reg32_lit32(variable_stack_offset) + dac_get_length_of_add_reg32_reg32() + dac_get_length_of_fstp_deref_register_as_qword(REGISTER_EDI); #endif } /* Get the length of the instructions generated by store_u_variable_on_stack() */ static u get_length_of_instructions_generated_by_store_u_variable_on_stack(Variable* cr variable) { u variable_stack_offset; assert_comparison(variable, !=, NULL, Variable*, void*); variable_stack_offset = ARROW(variable, stack_offset); #if SIXTY_FOUR_BIT if (variable_stack_offset) { return dac_get_length_of_mov_reg64_lit64(REGISTER_R11, variable_stack_offset) + dac_get_length_of_add_reg64_reg64() + dac_get_length_of_mov_deref_register_as_qword_reg64(REGISTER_R11); } else { return dac_get_length_of_mov_deref_register_as_qword_reg64(REGISTER_RSP); } #else if (variable_stack_offset) { return dac_get_length_of_mov_reg32_lit32(variable_stack_offset) + dac_get_length_of_add_reg32_reg32() + dac_get_length_of_mov_deref_register_as_dword_reg32(REGISTER_EDI); } else { return dac_get_length_of_mov_deref_register_as_dword_reg32(REGISTER_ESP); } #endif } u get_length_of_mid_level_instructions(MidLevelInstructions* cr mli) { u i; u length; assert_comparison(mli, !=, NULL, MidLevelInstructions*, void*); length = 0; for (i = 0; i < ARROW(mli, used_length); ++i) { MidLevelInstruction* const instruction = ARRAY_INDEX(ARROW(mli, mid_level_instructions), i); switch (ARROW(instruction, opcode)) { case MLI_OPCODE_MOV_UVAR_UVAL: { Variable* variable; OperandNode* operand_node; variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); operand_node = (OperandNode*)ARRAY_INDEX(instruction->arguments, 1); #if SIXTY_FOUR_BIT length += dac_get_length_of_mov_reg64_lit64(REGISTER_RAX, ARROW(operand_node, value).uvalue); #else length += dac_get_length_of_mov_reg32_lit32(ARROW(operand_node, value).uvalue); #endif if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_u_variable_on_stack(variable); } break; } case MLI_OPCODE_MOV_FVAR_FVAL: { Variable* variable; OperandNode* operand_node; variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); operand_node = (OperandNode*)ARRAY_INDEX(instruction->arguments, 1); assert_comparison(variable, !=, NULL, Variable*, void*); assert_comparison(operand_node, !=, NULL, OperandNode*, void*); if (ARROW(operand_node, value).fvalue == 0.0) { length += dac_get_length_of_fldz(); } else if (ARROW(operand_node, value).fvalue == 1.0) { length += dac_get_length_of_fld1(); } else { #if SIXTY_FOUR_BIT length += dac_get_length_of_mov_reg64_lit64(REGISTER_R11, DEREF((u*)ARROW(operand_node, address_in_memory))); length += dac_get_length_of_fld_deref_register_as_qword(REGISTER_R11); #else length += dac_get_length_of_mov_reg32_lit32(DEREF((u*)ARROW(operand_node, address_in_memory))); length += dac_get_length_of_fld_deref_register_as_qword(REGISTER_EDI); #endif } if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable); } break; } case MLI_OPCODE_MUL_UVAR_UVAL: output_nullt_string("mul_uvar_uval\n"); break; case MLI_OPCODE_MUL_FVAR_FVAL: { Variable* variable; OperandNode* operand_node; variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); operand_node = (OperandNode*)ARRAY_INDEX(instruction->arguments, 1); assert_comparison(variable, !=, NULL, Variable*, void*); assert_comparison(operand_node, !=, NULL, Variable*, void*); if (ARROW(operand_node, value).fvalue == 0.0) { #if SIXTY_FOUR_BIT length += dac_get_length_of_fstp_deref_register_as_qword(REGISTER_RAX); #else length += dac_get_length_of_fstp_deref_register_as_qword(REGISTER_EAX); #endif length += dac_get_length_of_fldz(); } else { #if SIXTY_FOUR_BIT length += dac_get_length_of_mov_reg64_lit64(REGISTER_R11, DEREF((u*)ARROW(operand_node, address_in_memory))); length += dac_get_length_of_fmul_deref_register_as_qword(REGISTER_R11); #else length += dac_get_length_of_mov_reg32_lit32(DEREF((u*)ARROW(operand_node, address_in_memory))); length += dac_get_length_of_fmul_deref_register_as_qword(REGISTER_EDI); #endif } if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable); } break; } case MLI_OPCODE_MOV_FVAR_FVAR: { Variable* variable1; Variable* variable2; u variable_stack_offset; variable1 = (Variable*)ARRAY_INDEX(instruction->arguments, 0); variable2 = ARROW((OperandNode*)ARRAY_INDEX(instruction->arguments, 1), variable); assert_comparison(variable1, !=, NULL, Variable*, void*); assert_comparison(variable2, !=, NULL, Variable*, void*); variable_stack_offset = ARROW(variable2, stack_offset); #if SIXTY_FOUR_BIT length += dac_get_length_of_mov_reg64_reg64(); length += dac_get_length_of_mov_reg64_lit64(REGISTER_R11, variable_stack_offset); length += dac_get_length_of_add_reg64_reg64(); length += dac_get_length_of_fld_deref_register_as_qword(REGISTER_R11); #else length += dac_get_length_of_mov_reg32_reg32(); length += dac_get_length_of_mov_reg32_lit32(variable_stack_offset); length += dac_get_length_of_add_reg32_reg32(); length += dac_get_length_of_fld_deref_register_as_qword(REGISTER_EDI); #endif if (instruction == ARROW(variable1, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable1); } break; } case MLI_OPCODE_ADD_UVAR_UVAL: { OperandNode* operand_node; Variable* variable; variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); operand_node = (OperandNode*)ARRAY_INDEX(instruction->arguments, 1); #if SIXTY_FOUR_BIT length += dac_get_length_of_mov_reg64_lit64(REGISTER_RBX, ARROW(operand_node, value).uvalue); length += dac_get_length_of_add_reg64_reg64(); #else length += dac_get_length_of_mov_reg32_lit32(ARROW(operand_node, value).uvalue); length += dac_get_length_of_add_reg32_reg32(); #endif if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_u_variable_on_stack(variable); } break; } case MLI_OPCODE_ADD_FVAR_FVAL: { Variable* variable; OperandNode* operand_node; variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); operand_node = (OperandNode*)ARRAY_INDEX(instruction->arguments, 1); assert_comparison(variable, !=, NULL, Variable*, void*); assert_comparison(operand_node, !=, NULL, OperandNode*, void*); if (ARROW(operand_node, value).fvalue == 0.0) { /* Don't add 0.0 to any number. */ } else if (ARROW(operand_node, value).fvalue == 1.0) { length += dac_get_length_of_fld1(); length += dac_get_length_of_faddp(); } else { #if SIXTY_FOUR_BIT length += dac_get_length_of_mov_reg64_lit64(REGISTER_R11, DEREF((u*)ARROW(operand_node, address_in_memory))); length += dac_get_length_of_fadd_deref_register_as_qword(REGISTER_R11); #else length += dac_get_length_of_mov_reg32_lit32(DEREF((u*)ARROW(operand_node, address_in_memory))); length += dac_get_length_of_fadd_deref_register_as_qword(REGISTER_EDI); #endif } if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable); } break; } case MLI_OPCODE_ADD_UVAR_UVAR: output_nullt_string("add_uvar_uvar\n"); break; case MLI_OPCODE_ADD_FVAR_FVAR: { Variable* variable1; Variable* variable2; u variable_stack_offset; variable1 = (Variable*)ARRAY_INDEX(instruction->arguments, 0); variable2 = (Variable*)ARRAY_INDEX(instruction->arguments, 1); assert_comparison(variable1, !=, NULL, Variable*, void*); assert_comparison(variable2, !=, NULL, Variable*, void*); variable_stack_offset = ARROW(variable2, stack_offset); #if SIXTY_FOUR_BIT length += dac_get_length_of_mov_reg64_reg64(); length += dac_get_length_of_mov_reg64_lit64(REGISTER_R11, variable_stack_offset); length += dac_get_length_of_add_reg64_reg64(); length += dac_get_length_of_fadd_deref_register_as_qword(REGISTER_R11); #else length += dac_get_length_of_mov_reg32_reg32(); length += dac_get_length_of_mov_reg32_lit32(variable_stack_offset); length += dac_get_length_of_add_reg32_reg32(); length += dac_get_length_of_fadd_deref_register_as_qword(REGISTER_EDI); #endif if (instruction == ARROW(variable1, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable1); } break; } case MLI_OPCODE_SUB_UVAR_UVAL: output_nullt_string("sub_uvar_uval\n"); break; case MLI_OPCODE_SUB_FVAR_FVAL: { Variable* variable; OperandNode* operand_node; variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); operand_node = (OperandNode*)ARRAY_INDEX(instruction->arguments, 1); assert_comparison(variable, !=, NULL, Variable*, void*); assert_comparison(operand_node, !=, NULL, OperandNode*, void*); if (ARROW(operand_node, value).fvalue == 1.0) { length += dac_get_length_of_fld1(); length += dac_get_length_of_fsubp(); } else { #if SIXTY_FOUR_BIT length += dac_get_length_of_mov_reg64_lit64(REGISTER_R11, DEREF((u*)ARROW(operand_node, address_in_memory))); length += dac_get_length_of_fsub_deref_register_as_qword(REGISTER_R11); #else length += dac_get_length_of_mov_reg32_lit32(DEREF((u*)ARROW(operand_node, address_in_memory))); length += dac_get_length_of_fsub_deref_register_as_qword(REGISTER_EDI); #endif } if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable); } break; } case MLI_OPCODE_SUB_UVAR_UVAR: output_nullt_string("sub_uvar_uvar\n"); break; case MLI_OPCODE_SUB_FVAR_FVAR: { Variable* variable1; Variable* variable2; u variable_stack_offset; variable1 = (Variable*)ARRAY_INDEX(instruction->arguments, 0); variable2 = (Variable*)ARRAY_INDEX(instruction->arguments, 1); assert_comparison(variable1, !=, NULL, Variable*, void*); assert_comparison(variable2, !=, NULL, Variable*, void*); variable_stack_offset = ARROW(variable2, stack_offset); #if SIXTY_FOUR_BIT length += dac_get_length_of_mov_reg64_reg64(); length += dac_get_length_of_mov_reg64_lit64(REGISTER_R11, variable_stack_offset); length += dac_get_length_of_add_reg64_reg64(); length += dac_get_length_of_fsub_deref_register_as_qword(REGISTER_R11); #else length += dac_get_length_of_mov_reg32_reg32(); length += dac_get_length_of_mov_reg32_lit32(variable_stack_offset); length += dac_get_length_of_add_reg32_reg32(); length += dac_get_length_of_fsub_deref_register_as_qword(REGISTER_EDI); #endif if (instruction == ARROW(variable1, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable1); } break; } case MLI_OPCODE_DIV_UVAR_UVAL: output_nullt_string("div_uvar_uval\n"); break; case MLI_OPCODE_DIV_FVAR_FVAL: /* FIXME */ assert_comparison(0, !=, 0, u, u); break; case MLI_OPCODE_CMP_LE_UVAR_UVAL: { Variable* variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable); } break; } case MLI_OPCODE_CMP_LT_UVAR_UVAL: { Variable* variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable); } break; } case MLI_OPCODE_CMP_EQ_UVAR_UVAL: { Variable* variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable); } break; } case MLI_OPCODE_CMP_NE_UVAR_UVAL: { Variable* variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable); } break; } case MLI_OPCODE_CMP_GT_UVAR_UVAL: { Variable* variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable); } break; } case MLI_OPCODE_CMP_GE_UVAR_UVAL: { Variable* variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable); } break; } case MLI_OPCODE_CMP_LE_FVAR_FVAL: { Variable* variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable); } break; } case MLI_OPCODE_CMP_LT_FVAR_FVAL: { Variable* variable; OperandNode* operand_node; u length_of_fld1_and_jmp_short; variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); operand_node = (OperandNode*)ARRAY_INDEX(instruction->arguments, 1); assert_comparison(variable, !=, NULL, Variable*, void*); assert_comparison(operand_node, !=, NULL, OperandNode*, void*); if (ARROW(operand_node, value).fvalue == 0.0) { length += dac_get_length_of_fldz(); } else if (ARROW(operand_node, value).fvalue == 1.0) { length += dac_get_length_of_fld1(); } else { #if SIXTY_FOUR_BIT length += dac_get_length_of_mov_reg64_lit64(REGISTER_R11, DEREF((u*)ARROW(operand_node, address_in_memory))); length += dac_get_length_of_fld_deref_register_as_qword(REGISTER_R11); #else length += dac_get_length_of_mov_reg32_lit32(DEREF((u*)ARROW(operand_node, address_in_memory))); length += dac_get_length_of_fld_deref_register_as_qword(REGISTER_EDI); #endif } length += dac_get_length_of_fcomip(); length += dac_get_length_of_fstp_fpu_register(); length_of_fld1_and_jmp_short = dac_get_length_of_fld1() + dac_get_length_of_jmp_short(); length += dac_get_length_of_jbe(length_of_fld1_and_jmp_short); length += length_of_fld1_and_jmp_short; length += dac_get_length_of_fldz(); if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable); } break; } case MLI_OPCODE_CMP_EQ_FVAR_FVAL: { Variable* variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable); } break; } case MLI_OPCODE_CMP_NE_FVAR_FVAL: { Variable* variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable); } break; } case MLI_OPCODE_CMP_GT_FVAR_FVAL: { Variable* variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable); } break; } case MLI_OPCODE_CMP_GE_FVAR_FVAL: { Variable* variable; OperandNode* operand_node; variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); operand_node = (OperandNode*)ARRAY_INDEX(instruction->arguments, 1); assert_comparison(variable, !=, NULL, Variable*, void*); assert_comparison(operand_node, !=, NULL, OperandNode*, void*); if (ARROW(operand_node, value).fvalue == 0.0) { length += dac_get_length_of_fldz(); } else if (ARROW(operand_node, value).fvalue == 1.0) { length += dac_get_length_of_fld1(); } else { #if SIXTY_FOUR_BIT length += dac_get_length_of_mov_reg64_lit64(REGISTER_R11, DEREF((u*)ARROW(operand_node, address_in_memory))); length += dac_get_length_of_fld_deref_register_as_qword(REGISTER_R11); #else length += dac_get_length_of_mov_reg32_lit32(DEREF((u*)ARROW(operand_node, address_in_memory))); length += dac_get_length_of_fld_deref_register_as_qword(REGISTER_EDI); #endif } length += dac_get_length_of_fcomip(); length += dac_get_length_of_fstp_fpu_register(); length += dac_get_length_of_jb_short(); length += dac_get_length_of_fld1(); length += dac_get_length_of_jmp_short(); length += dac_get_length_of_fldz(); if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable); } break; } case MLI_OPCODE_CMP_LE_UVAR_UVAR: { Variable* variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable); } break; } case MLI_OPCODE_CMP_LT_UVAR_UVAR: { Variable* variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable); } break; } case MLI_OPCODE_CMP_EQ_UVAR_UVAR: { Variable* variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable); } break; } case MLI_OPCODE_CMP_NE_UVAR_UVAR: { Variable* variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable); } break; } case MLI_OPCODE_CMP_GT_UVAR_UVAR: { Variable* variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable); } break; } case MLI_OPCODE_CMP_GE_UVAR_UVAR: { Variable* variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable); } break; } case MLI_OPCODE_CMP_LE_FVAR_FVAR: { Variable* variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable); } break; } case MLI_OPCODE_CMP_LT_FVAR_FVAR: { Variable* variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable); } break; } case MLI_OPCODE_CMP_EQ_FVAR_FVAR: { Variable* variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable); } break; } case MLI_OPCODE_CMP_NE_FVAR_FVAR: { Variable* variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable); } break; } case MLI_OPCODE_CMP_GT_FVAR_FVAR: { Variable* variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable); } break; } case MLI_OPCODE_CMP_GE_FVAR_FVAR: { Variable* variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable); } break; } case MLI_OPCODE_CHANGE_SIGN: { Variable* variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); length += dac_get_length_of_fchs(); if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable); } break; } case MLI_OPCODE_TEST_AND_JMP_IF_ZERO_FVAR_MEMADDR: { Variable* variable; u relative_instruction_offset; u variable_stack_offset; variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); assert_comparison(variable, !=, NULL, Variable*, void*); relative_instruction_offset = (u)ARRAY_INDEX(instruction->arguments, 1); if (likely(relative_instruction_offset)) { variable_stack_offset = ARROW(variable, stack_offset); #if SIXTY_FOUR_BIT length += dac_get_length_of_mov_reg64_reg64(); length += dac_get_length_of_mov_reg64_lit64(REGISTER_R12, variable_stack_offset); length += dac_get_length_of_add_reg64_reg64(); length += dac_get_length_of_fld_deref_register_as_qword(REGISTER_R11); #else length += dac_get_length_of_mov_reg32_reg32(); length += dac_get_length_of_mov_reg32_lit32(variable_stack_offset); length += dac_get_length_of_add_reg32_reg32(); length += dac_get_length_of_fld_deref_register_as_qword(REGISTER_EDI); #endif length += dac_get_length_of_fldz(); length += dac_get_length_of_fcomip(); length += dac_get_length_of_fstp_fpu_register(); length += dac_get_length_of_je(relative_instruction_offset); } if (instruction == ARROW(variable, last_instruction_that_uses_this_variable)) { length += get_length_of_instructions_generated_by_store_float_variable_on_stack(variable); } break; } case MLI_OPCODE_SEND_HELLO_WORLD_MESSAGE_TO_UI: { const u variable_stack_offset = (u)ARRAY_INDEX(instruction->arguments, 0); #if LINUX #if SIXTY_FOUR_BIT length += dac_get_length_of_mov_reg32_lit32(1 /* the system call number */); length += dac_get_length_of_mov_reg32_lit32(1); if (!variable_stack_offset) { length += dac_get_length_of_mov_deref_register_as_qword_lit32(REGISTER_RSP); length += dac_get_length_of_mov_reg64_reg64(); } else if ((s)variable_stack_offset == (schar)variable_stack_offset) { length += dac_get_length_of_mov_deref_register_as_qword_plus_signed_byte_offset_lit32(REGISTER_RSP); length += dac_get_length_of_mov_reg64_reg64(); length += dac_get_length_of_add_reg64_lit32(REGISTER_RSI, (s)ARRAY_INDEX(instruction->arguments, 0)); } else { length += dac_get_length_of_mov_reg64_reg64(); length += dac_get_length_of_mov_reg64_lit64(REGISTER_R11, (s)ARRAY_INDEX(instruction->arguments, 0) /* stack offset */); length += dac_get_length_of_add_reg64_reg64(); length += dac_get_length_of_mov_deref_register_as_qword_lit32(REGISTER_RSI); } length += dac_get_length_of_mov_reg32_lit32(2); length += dac_get_length_of_syscall(); #else length += dac_get_length_of_mov_reg32_lit32(4 /* the system call number */); length += dac_get_length_of_mov_reg32_lit32(1); if (!variable_stack_offset) { length += dac_get_length_of_mov_deref_register_as_dword_lit32(REGISTER_ESP); length += dac_get_length_of_mov_reg32_reg32(); } else if ((s)variable_stack_offset == (schar)variable_stack_offset) { length += dac_get_length_of_mov_deref_register_as_dword_plus_signed_byte_offset_lit32(REGISTER_ESP); length += dac_get_length_of_mov_reg32_reg32(); length += dac_get_length_of_add_reg32_lit32(REGISTER_ESI, (s)ARRAY_INDEX(instruction->arguments, 0)); } else { length += dac_get_length_of_mov_reg32_lit32(0 /* the message number */); length += dac_get_length_of_mov_reg32_reg32(); length += dac_get_length_of_mov_reg32_lit32((s)ARRAY_INDEX(instruction->arguments, 0) /* stack offset */); length += dac_get_length_of_add_reg32_reg32(); length += dac_get_length_of_mov_deref_register_as_dword_reg32(REGISTER_ECX); } length += dac_get_length_of_mov_reg32_lit32(2); length += dac_get_length_of_int(); #endif #else (void)variable_stack_offset; #endif break; } case MLI_OPCODE_SEND_OUTPUT_UINT_MESSAGE_TO_UI: { u variable_stack_offset = (u)ARRAY_INDEX(instruction->arguments, 0); Variable* variable = (Variable*)ARRAY_INDEX(instruction->arguments, 1); assert_comparison(variable, !=, NULL, Variable* cr, void*); #if SIXTY_FOUR_BIT length += dac_get_length_of_mov_reg32_lit32(1); length += dac_get_length_of_mov_reg64_lit64(REGISTER_RDI, 1); length += dac_get_length_of_mov_reg64_lit64(REGISTER_RDX, 10); length += dac_get_length_of_mov_reg64_reg64(); length += dac_get_length_of_mov_reg64_lit64(REGISTER_R11, variable_stack_offset); length += dac_get_length_of_add_reg64_reg64(); length += dac_get_length_of_mov_reg64_lit64(REGISTER_R12, 1); length += dac_get_length_of_mov_deref_register_as_qword_reg64(REGISTER_RSI); length += dac_get_length_of_add_reg64_lit32(REGISTER_RSI, 2); length += dac_get_length_of_mov_reg64_lit64(REGISTER_R12, (s)ARROW(variable, stack_offset)); length += dac_get_length_of_add_reg64_reg64(); length += dac_get_length_of_mov_reg64_deref_register_as_qword(REGISTER_R12); length += dac_get_length_of_mov_deref_register_as_qword_reg64(REGISTER_RSI); length += dac_get_length_of_sub_reg64_lit32(REGISTER_RSI, 2); length += dac_get_length_of_syscall(); #else (void)variable_stack_offset; #endif break; } case MLI_OPCODE_SEND_OUTPUT_FLOAT_MESSAGE_TO_UI: { u variable_stack_offset = (u)ARRAY_INDEX(instruction->arguments, 0); Variable* variable = (Variable*)ARRAY_INDEX(instruction->arguments, 1); assert_comparison(variable, !=, NULL, Variable* cr, void*); #if SIXTY_FOUR_BIT length += dac_get_length_of_mov_reg32_lit32(1); length += dac_get_length_of_mov_reg64_lit64(REGISTER_RDI, 1); length += dac_get_length_of_mov_reg64_lit64(REGISTER_RDX, 10); length += dac_get_length_of_mov_reg64_reg64(); length += dac_get_length_of_mov_reg64_lit64(REGISTER_R11, variable_stack_offset); length += dac_get_length_of_add_reg64_reg64(); length += dac_get_length_of_mov_reg64_lit64(REGISTER_R12, 2); length += dac_get_length_of_mov_deref_register_as_qword_reg64(REGISTER_RSI); length += dac_get_length_of_add_reg64_lit32(REGISTER_RSI, 2); length += dac_get_length_of_mov_reg64_lit64(REGISTER_R12, (s)ARROW(variable, stack_offset)); length += dac_get_length_of_add_reg64_reg64(); length += dac_get_length_of_mov_reg64_deref_register_as_qword(REGISTER_R12); length += dac_get_length_of_mov_deref_register_as_qword_reg64(REGISTER_RSI); length += dac_get_length_of_sub_reg64_lit32(REGISTER_RSI, 2); length += dac_get_length_of_syscall(); #else (void)variable_stack_offset; #endif break; } case MLI_OPCODE_ADD_MAIN_SUBROUTINE_STARTING_INSTRUCTIONS: { const u stack_offset = (u)ARRAY_INDEX(instruction->arguments, 0); if ( unlikely( i + 1 < ARROW(mli, used_length) && ARROW(ARRAY_INDEX(ARROW(mli, mid_level_instructions), i + 1), opcode) == MLI_OPCODE_ADD_MAIN_SUBROUTINE_ENDING_INSTRUCTIONS ) ) { length += dac_get_length_of_ret(); ++i; continue; } length += dac_get_length_of_pusha_except_stack_pointer(); if (stack_offset) { #if SIXTY_FOUR_BIT length += dac_get_length_of_mov_reg64_lit64_ten_byte_encoding(); length += dac_get_length_of_sub_reg64_reg64(); #else length += dac_get_length_of_mov_reg32_lit32(stack_offset); length += dac_get_length_of_sub_reg32_reg32(); #endif } break; } case MLI_OPCODE_ADD_MAIN_SUBROUTINE_ENDING_INSTRUCTIONS: { const u stack_offset = (u)ARRAY_INDEX(instruction->arguments, 0); if (stack_offset) { #if SIXTY_FOUR_BIT length += dac_get_length_of_mov_reg64_lit64(REGISTER_RBP, stack_offset); length += dac_get_length_of_add_reg64_reg64(); #else length += dac_get_length_of_mov_reg32_lit32(stack_offset); length += dac_get_length_of_add_reg32_reg32(); #endif } length += dac_get_length_of_popa_except_stack_pointer(); length += dac_get_length_of_ret(); break; } case MLI_OPCODE_ADD_SUBROUTINE_STARTING_INSTRUCTIONS: { #if SIXTY_FOUR_BIT length += dac_get_length_of_push(REGISTER_RBP); length += dac_get_length_of_mov_reg64_lit64_ten_byte_encoding(); length += dac_get_length_of_mov_reg64_reg64(); length += dac_get_length_of_sub_reg64_reg64(); #else #error "FIXME" #endif break; } case MLI_OPCODE_ADD_SUBROUTINE_ENDING_INSTRUCTIONS: { const u number_of_arguments = (u)ARRAY_INDEX(instruction->arguments, 0); #if SIXTY_FOUR_BIT length += dac_get_length_of_mov_reg64_reg64(); length += dac_get_length_of_add_reg64_lit32(REGISTER_RBX, 8); length += dac_get_length_of_mov_reg64_deref_register_as_qword(REGISTER_RBX); #else #error "FIXME" #endif #if SIXTY_FOUR_BIT length += dac_get_length_of_mov_reg64_reg64(); length += dac_get_length_of_pop(REGISTER_RBP); length += dac_get_length_of_mov_reg64_lit64(REGISTER_RBX, (number_of_arguments + 1) * 8); length += dac_get_length_of_add_reg64_reg64(); #else #error "FIXME" #endif #if SIXTY_FOUR_BIT length += dac_get_length_of_jmp_reg(REGISTER_RAX); #else length += dac_get_length_of_jmp_reg(REGISTER_EAX); #endif break; } case MLI_OPCODE_PUSH_ARGUMENT: { Variable* variable = (Variable*)ARRAY_INDEX(instruction->arguments, 0); #if SIXTY_FOUR_BIT length += dac_get_length_of_mov_reg64_lit64(REGISTER_R11, ARROW(variable, stack_offset)); length += dac_get_length_of_add_reg64_reg64(); length += dac_get_length_of_mov_reg64_deref_register_as_qword(REGISTER_R11); length += dac_get_length_of_push(REGISTER_RAX); #else length += dac_get_length_of_mov_reg32_lit32(ARROW(variable, stack_offset)); length += dac_get_length_of_add_reg32_reg32(); length += dac_get_length_of_mov_reg32_deref_register_as_dword(REGISTER_EDI); length += dac_get_length_of_push(); #endif break; } case MLI_OPCODE_CALL_SUBROUTINE: #if SIXTY_FOUR_BIT length += dac_get_length_of_mov_reg64_lit64_ten_byte_encoding(); length += dac_get_length_of_call_reg64(REGISTER_RDI); #else length += 5; length += dac_get_length_of_call_reg32(); #endif break; } } return length; }