X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=src%2Fexpressc.c;h=61a5d5aadb1f3a445a837e85babd72ae457d7fc9;hb=HEAD;hp=378582ed5d08873a74273d7ce6dcd99689a22bc9;hpb=c881aa3386c00d7021ffabf2f66275d6c110c1c1;p=inform.git diff --git a/src/expressc.c b/src/expressc.c index 378582e..61a5d5a 100644 --- a/src/expressc.c +++ b/src/expressc.c @@ -1,8 +1,8 @@ /* ------------------------------------------------------------------------- */ /* "expressc" : The expression code generator */ /* */ -/* Part of Inform 6.35 */ -/* copyright (c) Graham Nelson 1993 - 2021 */ +/* Part of Inform 6.42 */ +/* copyright (c) Graham Nelson 1993 - 2024 */ /* */ /* Inform is free software: you can redistribute it and/or modify */ /* it under the terms of the GNU General Public License as published by */ @@ -403,7 +403,7 @@ static void value_in_void_context_z(assembly_operand AO) case SHORT_CONSTANT_OT: t = ""; if (AO.marker == SYMBOL_MV) - t = (char *) (symbs[AO.value]); + t = (symbols[AO.value].name); break; case VARIABLE_OT: t = variable_name(AO.value); @@ -448,12 +448,14 @@ static void access_memory_z(int oc, assembly_operand AO1, assembly_operand AO2, assembly_operand zero_ao, max_ao, size_ao, en_ao, type_ao, an_ao, index_ao; - int x = 0, y = 0, byte_flag = FALSE, read_flag = FALSE, from_module = FALSE; + int x = 0, y = 0, byte_flag = FALSE, read_flag = FALSE; + + INITAO(&zero_ao); + INITAO(&size_ao); + INITAO(&type_ao); if (AO1.marker == ARRAY_MV || AO1.marker == STATIC_ARRAY_MV) { - INITAO(&zero_ao); - if ((oc == loadb_zc) || (oc == storeb_zc)) byte_flag=TRUE; else byte_flag = FALSE; if ((oc == loadb_zc) || (oc == loadw_zc)) read_flag=TRUE; @@ -464,33 +466,35 @@ static void access_memory_z(int oc, assembly_operand AO1, assembly_operand AO2, size_ao = zero_ao; size_ao.value = -1; for (x=0; x' to access a --> or table array"); } else { - if ((array_types[y] == BYTE_ARRAY) - || (array_types[y] == STRING_ARRAY)) + if ((arrays[y].type == BYTE_ARRAY) + || (arrays[y].type == STRING_ARRAY)) warning("Using '-->' to access a -> or string array"); } } @@ -509,7 +513,7 @@ static void access_memory_z(int oc, assembly_operand AO1, assembly_operand AO2, /* If we recognise AO1 as arising textually from a declared array, we can check bounds explicitly. */ - if ((AO1.marker == ARRAY_MV || AO1.marker == STATIC_ARRAY_MV) && (!from_module)) + if ((AO1.marker == ARRAY_MV || AO1.marker == STATIC_ARRAY_MV)) { int passed_label = next_label++, failed_label = next_label++, final_label = next_label++; @@ -518,15 +522,15 @@ static void access_memory_z(int oc, assembly_operand AO1, assembly_operand AO2, max_ao = size_ao; if (byte_flag - && ((array_types[y] == WORD_ARRAY) - || (array_types[y] == TABLE_ARRAY))) + && ((arrays[y].type == WORD_ARRAY) + || (arrays[y].type == TABLE_ARRAY))) { max_ao.value = size_ao.value*2 + 1; type_ao.value += 8; } if ((!byte_flag) - && ((array_types[y] == BYTE_ARRAY) - || (array_types[y] == STRING_ARRAY) - || (array_types[y] == BUFFER_ARRAY))) + && ((arrays[y].type == BYTE_ARRAY) + || (arrays[y].type == STRING_ARRAY) + || (arrays[y].type == BUFFER_ARRAY))) { if ((size_ao.value % 2) == 0) max_ao.value = size_ao.value/2 - 1; else max_ao.value = (size_ao.value-1)/2; @@ -538,10 +542,10 @@ static void access_memory_z(int oc, assembly_operand AO1, assembly_operand AO2, if (max_ao.value >= 256) max_ao.type = LONG_CONSTANT_OT; /* Can't write to the size entry in a string or table */ - if (((array_types[y] == STRING_ARRAY) - || (array_types[y] == TABLE_ARRAY)) + if (((arrays[y].type == STRING_ARRAY) + || (arrays[y].type == TABLE_ARRAY)) && (!read_flag)) - { if ((array_types[y] == TABLE_ARRAY) && byte_flag) + { if ((arrays[y].type == TABLE_ARRAY) && byte_flag) zero_ao.value = 2; else zero_ao.value = 1; } @@ -714,6 +718,25 @@ static void compile_conditional_z(int oc, ASSERT_ZCODE(); + switch (oc) { + case test_attr_zc: + check_warn_symbol_type(&AO1, OBJECT_T, 0, "\"has/hasnt\" expression"); + check_warn_symbol_type(&AO2, ATTRIBUTE_T, 0, "\"has/hasnt\" expression"); + break; + case jin_zc: + check_warn_symbol_type(&AO1, OBJECT_T, 0, "\"in/notin\" expression"); + check_warn_symbol_type(&AO2, OBJECT_T, CLASS_T, "\"in/notin\" expression"); + break; + case 200: + /* first argument can be anything */ + check_warn_symbol_type(&AO2, CLASS_T, 0, "\"ofclass\" expression"); + break; + case 201: + /* first argument can be anything */ + check_warn_symbol_type(&AO2, PROPERTY_T, INDIVIDUAL_PROPERTY_T, "\"provides\" expression"); + break; + } + if (oc<200) { if ((runtime_error_checking_switch) && (oc == jin_zc)) { if (flag) error_label = next_label++; @@ -783,7 +806,7 @@ static void value_in_void_context_g(assembly_operand AO) case ZEROCONSTANT_OT: t = ""; if (AO.marker == SYMBOL_MV) - t = (char *) (symbs[AO.value]); + t = (symbols[AO.value].name); break; case GLOBALVAR_OT: case LOCALVAR_OT: @@ -821,36 +844,38 @@ static void access_memory_g(int oc, assembly_operand AO1, assembly_operand AO2, else read_flag = FALSE; + INITAO(&zero_ao); + INITAO(&size_ao); + INITAO(&type_ao); + if (AO1.marker == ARRAY_MV || AO1.marker == STATIC_ARRAY_MV) { - INITAO(&zero_ao); - size_ao = zero_ao; size_ao.value = -1; for (x=0; x' to access a --> or table array"); } else { - if ((array_types[y] == BYTE_ARRAY) - || (array_types[y] == STRING_ARRAY)) + if ((arrays[y].type == BYTE_ARRAY) + || (arrays[y].type == STRING_ARRAY)) warning("Using '-->' to access a -> or string array"); } } @@ -872,25 +897,25 @@ static void access_memory_g(int oc, assembly_operand AO1, assembly_operand AO2, Here "size_ao.value" = largest permitted entry of its own kind */ max_ao = size_ao; if (data_len == 1 - && ((array_types[y] == WORD_ARRAY) - || (array_types[y] == TABLE_ARRAY))) + && ((arrays[y].type == WORD_ARRAY) + || (arrays[y].type == TABLE_ARRAY))) { max_ao.value = size_ao.value*4 + 3; type_ao.value += 8; } if (data_len == 4 - && ((array_types[y] == BYTE_ARRAY) - || (array_types[y] == STRING_ARRAY) - || (array_types[y] == BUFFER_ARRAY))) + && ((arrays[y].type == BYTE_ARRAY) + || (arrays[y].type == STRING_ARRAY) + || (arrays[y].type == BUFFER_ARRAY))) { max_ao.value = (size_ao.value-3)/4; type_ao.value += 16; } max_ao.value++; /* Can't write to the size entry in a string or table */ - if (((array_types[y] == STRING_ARRAY) - || (array_types[y] == TABLE_ARRAY)) + if (((arrays[y].type == STRING_ARRAY) + || (arrays[y].type == TABLE_ARRAY)) && (!read_flag)) - { if ((array_types[y] == TABLE_ARRAY) && data_len == 1) + { if ((arrays[y].type == TABLE_ARRAY) && data_len == 1) zero_ao.value = 4; else zero_ao.value = 1; } @@ -991,7 +1016,8 @@ static assembly_operand check_nonzero_at_runtime_g(assembly_operand AO1, assembly_operand AO, AO2, AO3; int ln; int check_sp = FALSE, passed_label, failed_label, last_label; - + int pre_unreach; + if (veneer_mode) return AO1; @@ -1013,6 +1039,8 @@ static assembly_operand check_nonzero_at_runtime_g(assembly_operand AO1, return AO1; } + pre_unreach = execution_never_reaches_here; + passed_label = next_label++; failed_label = next_label++; @@ -1033,6 +1061,8 @@ static assembly_operand check_nonzero_at_runtime_g(assembly_operand AO1, /* Allow classes */ /* Test if zero... */ assembleg_1_branch(jz_gc, AO, failed_label); + if (!pre_unreach && execution_never_reaches_here) + execution_never_reaches_here |= EXECSTATE_NOWARN; /* Test if first byte is 0x70... */ assembleg_3(aloadb_gc, AO, zero_operand, stack_pointer); INITAO(&AO3); @@ -1043,6 +1073,8 @@ static assembly_operand check_nonzero_at_runtime_g(assembly_operand AO1, else { /* Test if zero... */ assembleg_1_branch(jz_gc, AO, failed_label); + if (!pre_unreach && execution_never_reaches_here) + execution_never_reaches_here |= EXECSTATE_NOWARN; /* Test if first byte is 0x70... */ assembleg_3(aloadb_gc, AO, zero_operand, stack_pointer); INITAO(&AO3); @@ -1052,10 +1084,16 @@ static assembly_operand check_nonzero_at_runtime_g(assembly_operand AO1, /* Test if inside the "Class" object... */ INITAOTV(&AO3, BYTECONSTANT_OT, GOBJFIELD_PARENT()); assembleg_3(aload_gc, AO, AO3, stack_pointer); - ln = symbol_index("Class", -1); - AO3.value = svals[ln]; - AO3.marker = OBJECT_MV; - AO3.type = CONSTANT_OT; + ln = get_symbol_index("Class"); + if (ln < 0) { + error("No 'Class' object found"); + AO3 = zero_operand; + } + else { + AO3.value = symbols[ln].value; + AO3.marker = OBJECT_MV; + AO3.type = CONSTANT_OT; + } assembleg_2_branch(jne_gc, stack_pointer, AO3, passed_label); } @@ -1073,10 +1111,16 @@ static assembly_operand check_nonzero_at_runtime_g(assembly_operand AO1, } else { /* Build the symbol for "Object" */ - ln = symbol_index("Object", -1); - AO2.value = svals[ln]; - AO2.marker = OBJECT_MV; - AO2.type = CONSTANT_OT; + ln = get_symbol_index("Object"); + if (ln < 0) { + error("No 'Object' object found"); + AO2 = zero_operand; + } + else { + AO2.value = symbols[ln].value; + AO2.marker = OBJECT_MV; + AO2.type = CONSTANT_OT; + } if (check_sp) { /* Push "Object" */ assembleg_store(AO1, AO2); @@ -1112,6 +1156,8 @@ static void compile_conditional_g(condclass *cc, switch ((cc-condclasses)*2 + 500) { case HAS_CC: + check_warn_symbol_type(&AO1, OBJECT_T, 0, "\"has/hasnt\" expression"); + check_warn_symbol_type(&AO2, ATTRIBUTE_T, 0, "\"has/hasnt\" expression"); if (runtime_error_checking_switch) { if (flag) error_label = next_label++; @@ -1190,6 +1236,8 @@ static void compile_conditional_g(condclass *cc, break; case IN_CC: + check_warn_symbol_type(&AO1, OBJECT_T, 0, "\"in/notin\" expression"); + check_warn_symbol_type(&AO2, OBJECT_T, CLASS_T, "\"in/notin\" expression"); if (runtime_error_checking_switch) { if (flag) error_label = next_label++; @@ -1204,12 +1252,16 @@ static void compile_conditional_g(condclass *cc, break; case OFCLASS_CC: + /* first argument can be anything */ + check_warn_symbol_type(&AO2, CLASS_T, 0, "\"ofclass\" expression"); assembleg_call_2(veneer_routine(OC__Cl_VR), AO1, AO2, stack_pointer); the_zc = (flag ? jnz_gc : jz_gc); AO1 = stack_pointer; break; case PROVIDES_CC: + /* first argument can be anything */ + check_warn_symbol_type(&AO2, PROPERTY_T, INDIVIDUAL_PROPERTY_T, "\"provides\" expression"); assembleg_call_2(veneer_routine(OP__Pr_VR), AO1, AO2, stack_pointer); the_zc = (flag ? jnz_gc : jz_gc); AO1 = stack_pointer; @@ -1271,6 +1323,12 @@ static void generate_code_from(int n, int void_flag) if ((opnum == LOGAND_OP) || (opnum == LOGOR_OP)) { generate_code_from(below, FALSE); + if (execution_never_reaches_here) { + /* If the condition never falls through to here, then it + was an "... && 0 && ..." test. Our convention is to skip + the "not reached" warnings for this case. */ + execution_never_reaches_here |= EXECSTATE_NOWARN; + } generate_code_from(ET[below].right, FALSE); goto OperatorGenerated; } @@ -1681,6 +1739,8 @@ static void generate_code_from(int n, int void_flag) case PROP_ADD_OP: { assembly_operand AO = ET[below].value; + check_warn_symbol_type(&ET[below].value, OBJECT_T, CLASS_T, "\".&\" expression"); + check_warn_symbol_type(&ET[ET[below].right].value, PROPERTY_T, INDIVIDUAL_PROPERTY_T, "\".&\" expression"); if (runtime_error_checking_switch && (!veneer_mode)) AO = check_nonzero_at_runtime(AO, -1, PROP_ADD_RTE); assemblez_2_to(get_prop_addr_zc, AO, @@ -1691,6 +1751,8 @@ static void generate_code_from(int n, int void_flag) case PROP_NUM_OP: { assembly_operand AO = ET[below].value; + check_warn_symbol_type(&ET[below].value, OBJECT_T, CLASS_T, "\".#\" expression"); + check_warn_symbol_type(&ET[ET[below].right].value, PROPERTY_T, INDIVIDUAL_PROPERTY_T, "\".#\" expression"); if (runtime_error_checking_switch && (!veneer_mode)) AO = check_nonzero_at_runtime(AO, -1, PROP_NUM_RTE); assemblez_2_to(get_prop_addr_zc, AO, @@ -1703,49 +1765,70 @@ static void generate_code_from(int n, int void_flag) break; case PROPERTY_OP: - { assembly_operand AO = ET[below].value; - + { + check_warn_symbol_type(&ET[below].value, OBJECT_T, CLASS_T, "\".\" expression"); + check_warn_symbol_type(&ET[ET[below].right].value, PROPERTY_T, INDIVIDUAL_PROPERTY_T, "\".\" expression"); if (runtime_error_checking_switch && (!veneer_mode)) assemblez_3_to(call_vs_zc, veneer_routine(RT__ChPR_VR), - AO, ET[ET[below].right].value, temp_var1); + ET[below].value, ET[ET[below].right].value, temp_var1); else - assemblez_2_to(get_prop_zc, AO, + assemblez_2_to(get_prop_zc, ET[below].value, ET[ET[below].right].value, temp_var1); if (!void_flag) write_result_z(Result, temp_var1); } break; case MESSAGE_OP: + check_warn_symbol_type(&ET[below].value, OBJECT_T, CLASS_T, "\".\" expression"); + check_warn_symbol_type(&ET[ET[below].right].value, PROPERTY_T, INDIVIDUAL_PROPERTY_T, "\".\" expression"); j=1; AI.operand[0] = veneer_routine(RV__Pr_VR); goto GenFunctionCallZ; case MPROP_ADD_OP: + check_warn_symbol_type(&ET[below].value, OBJECT_T, CLASS_T, "\".&\" expression"); + check_warn_symbol_type(&ET[ET[below].right].value, PROPERTY_T, INDIVIDUAL_PROPERTY_T, "\".&\" expression"); j=1; AI.operand[0] = veneer_routine(RA__Pr_VR); goto GenFunctionCallZ; case MPROP_NUM_OP: + check_warn_symbol_type(&ET[below].value, OBJECT_T, CLASS_T, "\".#\" expression"); + check_warn_symbol_type(&ET[ET[below].right].value, PROPERTY_T, INDIVIDUAL_PROPERTY_T, "\".#\" expression"); j=1; AI.operand[0] = veneer_routine(RL__Pr_VR); goto GenFunctionCallZ; case MESSAGE_SETEQUALS_OP: + check_warn_symbol_type(&ET[below].value, OBJECT_T, CLASS_T, "\".\" expression"); + check_warn_symbol_type(&ET[ET[below].right].value, PROPERTY_T, INDIVIDUAL_PROPERTY_T, "\".\" expression"); j=1; AI.operand[0] = veneer_routine(WV__Pr_VR); goto GenFunctionCallZ; case MESSAGE_INC_OP: + check_warn_symbol_type(&ET[below].value, OBJECT_T, CLASS_T, "\"++.\" expression"); + check_warn_symbol_type(&ET[ET[below].right].value, PROPERTY_T, INDIVIDUAL_PROPERTY_T, "\"++.\" expression"); j=1; AI.operand[0] = veneer_routine(IB__Pr_VR); goto GenFunctionCallZ; case MESSAGE_DEC_OP: + check_warn_symbol_type(&ET[below].value, OBJECT_T, CLASS_T, "\"--.\" expression"); + check_warn_symbol_type(&ET[ET[below].right].value, PROPERTY_T, INDIVIDUAL_PROPERTY_T, "\"--.\" expression"); j=1; AI.operand[0] = veneer_routine(DB__Pr_VR); goto GenFunctionCallZ; case MESSAGE_POST_INC_OP: + check_warn_symbol_type(&ET[below].value, OBJECT_T, CLASS_T, "\".++\" expression"); + check_warn_symbol_type(&ET[ET[below].right].value, PROPERTY_T, INDIVIDUAL_PROPERTY_T, "\".++\" expression"); j=1; AI.operand[0] = veneer_routine(IA__Pr_VR); goto GenFunctionCallZ; case MESSAGE_POST_DEC_OP: + check_warn_symbol_type(&ET[below].value, OBJECT_T, CLASS_T, "\".--\" expression"); + check_warn_symbol_type(&ET[ET[below].right].value, PROPERTY_T, INDIVIDUAL_PROPERTY_T, "\".--\" expression"); j=1; AI.operand[0] = veneer_routine(DA__Pr_VR); goto GenFunctionCallZ; case SUPERCLASS_OP: j=1; AI.operand[0] = veneer_routine(RA__Sc_VR); goto GenFunctionCallZ; case PROP_CALL_OP: + check_warn_symbol_has_metaclass(&ET[below].value, "\".()\" expression"); + check_warn_symbol_type(&ET[ET[below].right].value, PROPERTY_T, INDIVIDUAL_PROPERTY_T, "\".()\" expression"); j=1; AI.operand[0] = veneer_routine(CA__Pr_VR); goto GenFunctionCallZ; case MESSAGE_CALL_OP: + check_warn_symbol_has_metaclass(&ET[below].value, "\".()\" expression"); + check_warn_symbol_type(&ET[ET[below].right].value, PROPERTY_T, INDIVIDUAL_PROPERTY_T, "\".()\" expression"); j=1; AI.operand[0] = veneer_routine(CA__Pr_VR); goto GenFunctionCallZ; @@ -1849,6 +1932,7 @@ static void generate_code_from(int n, int void_flag) case INDIRECT_SYSF: j=0; i = ET[below].right; + check_warn_symbol_type(&ET[i].value, ROUTINE_T, 0, "indirect function call"); goto IndirectFunctionCallZ; case CHILDREN_SYSF: @@ -1924,6 +2008,7 @@ static void generate_code_from(int n, int void_flag) } break; } + check_warn_symbol_type(&ET[below].value, ROUTINE_T, 0, "function call"); GenFunctionCallZ: @@ -1981,6 +2066,8 @@ static void generate_code_from(int n, int void_flag) break; case PROPERTY_SETEQUALS_OP: + check_warn_symbol_type(&ET[below].value, OBJECT_T, CLASS_T, "\".\" expression"); + check_warn_symbol_type(&ET[ET[below].right].value, PROPERTY_T, INDIVIDUAL_PROPERTY_T, "\".\" expression"); if (!void_flag) { if (runtime_error_checking_switch) assemblez_4_to(call_zc, veneer_routine(RT__ChPS_VR), @@ -2124,6 +2211,8 @@ static void generate_code_from(int n, int void_flag) break; case PROPERTY_INC_OP: + check_warn_symbol_type(&ET[below].value, OBJECT_T, CLASS_T, "\"++.\" expression"); + check_warn_symbol_type(&ET[ET[below].right].value, PROPERTY_T, INDIVIDUAL_PROPERTY_T, "\"++.\" expression"); assemblez_store(temp_var1, ET[below].value); assemblez_store(temp_var2, ET[ET[below].right].value); assemblez_2_to(get_prop_zc, temp_var1, temp_var2, temp_var3); @@ -2136,6 +2225,8 @@ static void generate_code_from(int n, int void_flag) break; case PROPERTY_DEC_OP: + check_warn_symbol_type(&ET[below].value, OBJECT_T, CLASS_T, "\"--.\" expression"); + check_warn_symbol_type(&ET[ET[below].right].value, PROPERTY_T, INDIVIDUAL_PROPERTY_T, "\"--.\" expression"); assemblez_store(temp_var1, ET[below].value); assemblez_store(temp_var2, ET[ET[below].right].value); assemblez_2_to(get_prop_zc, temp_var1, temp_var2, temp_var3); @@ -2148,6 +2239,8 @@ static void generate_code_from(int n, int void_flag) break; case PROPERTY_POST_INC_OP: + check_warn_symbol_type(&ET[below].value, OBJECT_T, CLASS_T, "\".++\" expression"); + check_warn_symbol_type(&ET[ET[below].right].value, PROPERTY_T, INDIVIDUAL_PROPERTY_T, "\".++\" expression"); assemblez_store(temp_var1, ET[below].value); assemblez_store(temp_var2, ET[ET[below].right].value); assemblez_2_to(get_prop_zc, temp_var1, temp_var2, temp_var3); @@ -2160,6 +2253,8 @@ static void generate_code_from(int n, int void_flag) break; case PROPERTY_POST_DEC_OP: + check_warn_symbol_type(&ET[below].value, OBJECT_T, CLASS_T, "\".--\" expression"); + check_warn_symbol_type(&ET[ET[below].right].value, PROPERTY_T, INDIVIDUAL_PROPERTY_T, "\".--\" expression"); assemblez_store(temp_var1, ET[below].value); assemblez_store(temp_var2, ET[ET[below].right].value); assemblez_2_to(get_prop_zc, temp_var1, temp_var2, temp_var3); @@ -2177,7 +2272,7 @@ static void generate_code_from(int n, int void_flag) compiler_error("Expr code gen: Can't generate yet"); } } - else { + else { /* Glulx */ assembly_operand AO, AO2; if (operators[opnum].opcode_number_g != -1) { @@ -2371,37 +2466,53 @@ static void generate_code_from(int n, int void_flag) case PROPERTY_OP: case MESSAGE_OP: + check_warn_symbol_type(&ET[below].value, OBJECT_T, CLASS_T, "\".\" expression"); + check_warn_symbol_type(&ET[ET[below].right].value, PROPERTY_T, INDIVIDUAL_PROPERTY_T, "\".\" expression"); AO = veneer_routine(RV__Pr_VR); goto TwoArgFunctionCall; case MPROP_ADD_OP: case PROP_ADD_OP: + check_warn_symbol_type(&ET[below].value, OBJECT_T, CLASS_T, "\".&\" expression"); + check_warn_symbol_type(&ET[ET[below].right].value, PROPERTY_T, INDIVIDUAL_PROPERTY_T, "\".&\" expression"); AO = veneer_routine(RA__Pr_VR); goto TwoArgFunctionCall; case MPROP_NUM_OP: case PROP_NUM_OP: + check_warn_symbol_type(&ET[below].value, OBJECT_T, CLASS_T, "\".#\" expression"); + check_warn_symbol_type(&ET[ET[below].right].value, PROPERTY_T, INDIVIDUAL_PROPERTY_T, "\".#\" expression"); AO = veneer_routine(RL__Pr_VR); goto TwoArgFunctionCall; case PROP_CALL_OP: case MESSAGE_CALL_OP: + check_warn_symbol_has_metaclass(&ET[below].value, "\".()\" expression"); + check_warn_symbol_type(&ET[ET[below].right].value, PROPERTY_T, INDIVIDUAL_PROPERTY_T, "\".()\" expression"); AO2 = veneer_routine(CA__Pr_VR); i = below; goto DoFunctionCall; case MESSAGE_INC_OP: case PROPERTY_INC_OP: + check_warn_symbol_type(&ET[below].value, OBJECT_T, CLASS_T, "\"++.\" expression"); + check_warn_symbol_type(&ET[ET[below].right].value, PROPERTY_T, INDIVIDUAL_PROPERTY_T, "\"++.\" expression"); AO = veneer_routine(IB__Pr_VR); goto TwoArgFunctionCall; case MESSAGE_DEC_OP: case PROPERTY_DEC_OP: + check_warn_symbol_type(&ET[below].value, OBJECT_T, CLASS_T, "\"--.\" expression"); + check_warn_symbol_type(&ET[ET[below].right].value, PROPERTY_T, INDIVIDUAL_PROPERTY_T, "\"--.\" expression"); AO = veneer_routine(DB__Pr_VR); goto TwoArgFunctionCall; case MESSAGE_POST_INC_OP: case PROPERTY_POST_INC_OP: + check_warn_symbol_type(&ET[below].value, OBJECT_T, CLASS_T, "\".++\" expression"); + check_warn_symbol_type(&ET[ET[below].right].value, PROPERTY_T, INDIVIDUAL_PROPERTY_T, "\".++\" expression"); AO = veneer_routine(IA__Pr_VR); goto TwoArgFunctionCall; case MESSAGE_POST_DEC_OP: case PROPERTY_POST_DEC_OP: + check_warn_symbol_type(&ET[below].value, OBJECT_T, CLASS_T, "\".--\" expression"); + check_warn_symbol_type(&ET[ET[below].right].value, PROPERTY_T, INDIVIDUAL_PROPERTY_T, "\".--\" expression"); AO = veneer_routine(DA__Pr_VR); goto TwoArgFunctionCall; case SUPERCLASS_OP: @@ -2421,6 +2532,8 @@ static void generate_code_from(int n, int void_flag) case PROPERTY_SETEQUALS_OP: case MESSAGE_SETEQUALS_OP: + check_warn_symbol_type(&ET[below].value, OBJECT_T, CLASS_T, "\".\" expression"); + check_warn_symbol_type(&ET[ET[below].right].value, PROPERTY_T, INDIVIDUAL_PROPERTY_T, "\".\" expression"); if (runtime_error_checking_switch && (!veneer_mode)) AO = veneer_routine(RT__ChPS_VR); else @@ -2542,11 +2655,48 @@ static void generate_code_from(int n, int void_flag) assembleg_2(random_gc, AO, stack_pointer); assembleg_3(aload_gc, AO2, stack_pointer, Result); } + else if (is_constant_ot(ET[ET[below].right].value.type) && ET[ET[below].right].value.marker == 0) { + /* One argument, value known at compile time */ + int32 arg = ET[ET[below].right].value.value; /* signed */ + if (arg > 0) { + assembly_operand AO; + INITAO(&AO); + AO.value = arg; + set_constant_ot(&AO); + assembleg_2(random_gc, + AO, stack_pointer); + assembleg_3(add_gc, stack_pointer, one_operand, + Result); + } + else { + /* This handles zero or negative */ + assembly_operand AO; + INITAO(&AO); + AO.value = -arg; + set_constant_ot(&AO); + assembleg_1(setrandom_gc, + AO); + assembleg_store(Result, zero_operand); + } + } else { + /* One argument, not known at compile time */ + int ln, ln2; + assembleg_store(temp_var1, ET[ET[below].right].value); + ln = next_label++; + ln2 = next_label++; + assembleg_2_branch(jle_gc, temp_var1, zero_operand, ln); assembleg_2(random_gc, - ET[ET[below].right].value, stack_pointer); + temp_var1, stack_pointer); assembleg_3(add_gc, stack_pointer, one_operand, Result); + assembleg_0_branch(jump_gc, ln2); + assemble_label_no(ln); + assembleg_2(neg_gc, temp_var1, stack_pointer); + assembleg_1(setrandom_gc, + stack_pointer); + assembleg_store(Result, zero_operand); + assemble_label_no(ln2); } break; @@ -2611,6 +2761,7 @@ static void generate_code_from(int n, int void_flag) case INDIRECT_SYSF: i = ET[below].right; + check_warn_symbol_type(&ET[i].value, ROUTINE_T, 0, "indirect function call"); goto IndirectFunctionCallG; case GLK_SYSF: @@ -2680,6 +2831,7 @@ static void generate_code_from(int n, int void_flag) break; } + check_warn_symbol_type(&ET[below].value, ROUTINE_T, 0, "function call"); i = below; IndirectFunctionCallG: @@ -2772,6 +2924,7 @@ static void generate_code_from(int n, int void_flag) if (ET[n].to_expression) { + int32 donelabel; if (void_flag) { warning("Logical expression has no side-effects"); if (ET[n].true_label != -1) @@ -2780,18 +2933,26 @@ static void generate_code_from(int n, int void_flag) assemble_label_no(ET[n].false_label); } else if (ET[n].true_label != -1) - { assemblez_1(push_zc, zero_operand); - assemblez_jump(next_label++); + { + donelabel = next_label++; + if (!execution_never_reaches_here) { + assemblez_1(push_zc, zero_operand); + assemblez_jump(donelabel); + } assemble_label_no(ET[n].true_label); assemblez_1(push_zc, one_operand); - assemble_label_no(next_label-1); + assemble_forward_label_no(donelabel); } else - { assemblez_1(push_zc, one_operand); - assemblez_jump(next_label++); + { + donelabel = next_label++; + if (!execution_never_reaches_here) { + assemblez_1(push_zc, one_operand); + assemblez_jump(donelabel); + } assemble_label_no(ET[n].false_label); assemblez_1(push_zc, zero_operand); - assemble_label_no(next_label-1); + assemble_forward_label_no(donelabel); } ET[n].value = stack_pointer; } @@ -2804,6 +2965,7 @@ static void generate_code_from(int n, int void_flag) if (ET[n].to_expression) { + int32 donelabel; if (void_flag) { warning("Logical expression has no side-effects"); if (ET[n].true_label != -1) @@ -2812,18 +2974,26 @@ static void generate_code_from(int n, int void_flag) assemble_label_no(ET[n].false_label); } else if (ET[n].true_label != -1) - { assembleg_store(stack_pointer, zero_operand); - assembleg_jump(next_label++); + { + donelabel = next_label++; + if (!execution_never_reaches_here) { + assembleg_store(stack_pointer, zero_operand); + assembleg_jump(donelabel); + } assemble_label_no(ET[n].true_label); assembleg_store(stack_pointer, one_operand); - assemble_label_no(next_label-1); + assemble_forward_label_no(donelabel); } else - { assembleg_store(stack_pointer, one_operand); - assembleg_jump(next_label++); + { + donelabel = next_label++; + if (!execution_never_reaches_here) { + assembleg_store(stack_pointer, one_operand); + assembleg_jump(donelabel); + } assemble_label_no(ET[n].false_label); assembleg_store(stack_pointer, zero_operand); - assemble_label_no(next_label-1); + assemble_forward_label_no(donelabel); } ET[n].value = stack_pointer; } @@ -2880,7 +3050,7 @@ assembly_operand code_generate(assembly_operand AO, int context, int label) } if (expr_trace_level >= 2) - { printf("Raw parse tree:\n"); show_tree(AO, FALSE); + { printf("Raw parse tree:\n"); show_tree(&AO, FALSE); } if (context == CONDITION_CONTEXT) @@ -2900,7 +3070,7 @@ assembly_operand code_generate(assembly_operand AO, int context, int label) default: printf("* ILLEGAL *"); break; } printf(" context with annotated tree:\n"); - show_tree(AO, TRUE); + show_tree(&AO, TRUE); } generate_code_from(AO.value, (context==VOID_CONTEXT));