update variable type and add float type in script enginr

This commit is contained in:
xmaple555 2026-07-20 23:21:34 +08:00
parent ec5fe7cc8a
commit d44c726dff
25 changed files with 3595 additions and 1301 deletions

View file

@ -34,6 +34,20 @@ object ScriptConstants {
val SYMBOL_VALUE_KIND_INTEGER = 0
val SYMBOL_VALUE_KIND_FLOAT32 = 1
val SYMBOL_VALUE_KIND_FLOAT64 = 2
val SCRIPT_SCALAR_TYPE_INVALID = 0
val SCRIPT_SCALAR_TYPE_BOOL = 1
val SCRIPT_SCALAR_TYPE_I8 = 2
val SCRIPT_SCALAR_TYPE_I16 = 3
val SCRIPT_SCALAR_TYPE_I32 = 4
val SCRIPT_SCALAR_TYPE_I64 = 5
val SCRIPT_SCALAR_TYPE_U8 = 6
val SCRIPT_SCALAR_TYPE_U16 = 7
val SCRIPT_SCALAR_TYPE_U32 = 8
val SCRIPT_SCALAR_TYPE_U64 = 9
val SCRIPT_SCALAR_TYPE_F32 = 10
val SCRIPT_SCALAR_TYPE_F64 = 11
val SCRIPT_SCALAR_TYPE_POINTER = 12
val SCRIPT_SCALAR_TYPE_F80 = 13
}
/**
@ -48,6 +62,6 @@ object ScriptConstantTypes {
object ScriptEvalFunc {
object ScriptOperators extends ChiselEnum {
val sFuncUndefined, sFuncInc, sFuncDec, sFuncReference, sFuncOr, sFuncXor, sFuncAnd, sFuncAsr, sFuncAsl, sFuncAdd, sFuncSub, sFuncMul, sFuncDiv, sFuncMod, sFuncGt, sFuncLt, sFuncEgt, sFuncElt, sFuncEqual, sFuncNeq, sFuncJmp, sFuncJz, sFuncJnz, sFuncMov, sFuncStart_of_do_while, sFuncStart_of_do_while_commands, sFuncEnd_of_do_while, sFuncStart_of_for, sFuncFor_inc_dec, sFuncStart_of_for_ommands, sFuncEnd_of_if, sFuncIgnore_lvalue, sFuncPush, sFuncPop, sFuncCall, sFuncRet, sFuncPrint, sFuncFormats, sFuncEvent_enable, sFuncEvent_disable, sFuncEvent_clear, sFuncTest_statement, sFuncSpinlock_lock, sFuncSpinlock_unlock, sFuncEvent_sc, sFuncMicrosleep, sFuncPrintf, sFuncPause, sFuncFlush, sFuncEvent_trace_step, sFuncEvent_trace_step_in, sFuncEvent_trace_step_out, sFuncEvent_trace_instrumentation_step, sFuncEvent_trace_instrumentation_step_in, sFuncRdtsc, sFuncRdtscp, sFuncLbr_save, sFuncLbr_dump, sFuncLbr_print, sFuncLbr_restore, sFuncLbr_check, sFuncSpinlock_lock_custom_wait, sFuncEvent_inject, sFuncPoi, sFuncDb, sFuncDd, sFuncDw, sFuncDq, sFuncNeg, sFuncHi, sFuncLow, sFuncNot, sFuncCheck_address, sFuncDisassemble_len, sFuncDisassemble_len32, sFuncDisassemble_len64, sFuncInterlocked_increment, sFuncInterlocked_decrement, sFuncPhysical_to_virtual, sFuncVirtual_to_physical, sFuncPoi_pa, sFuncHi_pa, sFuncLow_pa, sFuncDb_pa, sFuncDd_pa, sFuncDw_pa, sFuncDq_pa, sFuncLbr_restore_by_filter, sFuncEd, sFuncEb, sFuncEq, sFuncInterlocked_exchange, sFuncInterlocked_exchange_add, sFuncEb_pa, sFuncEd_pa, sFuncEq_pa, sFuncInterlocked_compare_exchange, sFuncStrlen, sFuncStrcmp, sFuncMemcmp, sFuncStrncmp, sFuncWcslen, sFuncWcscmp, sFuncEvent_inject_error_code, sFuncMemcpy, sFuncMemcpy_pa, sFuncWcsncmp, sFuncStruct_forward_declaration, sFuncStruct_definition_begin, sFuncStruct_definition_end, sFuncStruct_variable_declaration, sFuncStruct_member_declaration, sFuncTypedef_declaration, sFuncStruct_pointer, sFuncStruct_array_dimension, sFuncStruct_declarator_complete, sFuncTyped_load, sFuncTyped_store, sFuncAggregate_copy, sFuncAggregate_zero, sFuncStruct_initializer_begin, sFuncStruct_initializer_end, sFuncStruct_pointer_cast, sFuncMember_address, sFuncMember_read, sFuncMember_dot_lvalue, sFuncMember_arrow_lvalue, sFuncMember_dot_read, sFuncMember_arrow_read, sFuncMov_float, sFuncNeg_float, sFuncAdd_float, sFuncSub_float, sFuncMul_float, sFuncDiv_float, sFuncGt_float, sFuncLt_float, sFuncEgt_float, sFuncElt_float, sFuncEqual_float, sFuncNeq_float, sFuncConvert_float = Value
val sFuncUndefined, sFuncInc, sFuncDec, sFuncReference, sFuncOr, sFuncXor, sFuncAnd, sFuncAsr, sFuncAsl, sFuncAdd, sFuncSub, sFuncMul, sFuncDiv, sFuncMod, sFuncGt, sFuncLt, sFuncEgt, sFuncElt, sFuncEqual, sFuncNeq, sFuncJmp, sFuncJz, sFuncJnz, sFuncMov, sFuncStart_of_do_while, sFuncStart_of_do_while_commands, sFuncEnd_of_do_while, sFuncStart_of_for, sFuncFor_inc_dec, sFuncStart_of_for_ommands, sFuncEnd_of_if, sFuncIgnore_lvalue, sFuncPush, sFuncPop, sFuncCall, sFuncRet, sFuncPrint, sFuncFormats, sFuncEvent_enable, sFuncEvent_disable, sFuncEvent_clear, sFuncTest_statement, sFuncSpinlock_lock, sFuncSpinlock_unlock, sFuncEvent_sc, sFuncMicrosleep, sFuncPrintf, sFuncPause, sFuncFlush, sFuncEvent_trace_step, sFuncEvent_trace_step_in, sFuncEvent_trace_step_out, sFuncEvent_trace_instrumentation_step, sFuncEvent_trace_instrumentation_step_in, sFuncRdtsc, sFuncRdtscp, sFuncLbr_save, sFuncLbr_dump, sFuncLbr_print, sFuncLbr_restore, sFuncLbr_check, sFuncSpinlock_lock_custom_wait, sFuncEvent_inject, sFuncPoi, sFuncDb, sFuncDd, sFuncDw, sFuncDq, sFuncNeg, sFuncHi, sFuncLow, sFuncNot, sFuncCheck_address, sFuncDisassemble_len, sFuncDisassemble_len32, sFuncDisassemble_len64, sFuncInterlocked_increment, sFuncInterlocked_decrement, sFuncPhysical_to_virtual, sFuncVirtual_to_physical, sFuncPoi_pa, sFuncHi_pa, sFuncLow_pa, sFuncDb_pa, sFuncDd_pa, sFuncDw_pa, sFuncDq_pa, sFuncLbr_restore_by_filter, sFuncEd, sFuncEb, sFuncEq, sFuncInterlocked_exchange, sFuncInterlocked_exchange_add, sFuncEb_pa, sFuncEd_pa, sFuncEq_pa, sFuncInterlocked_compare_exchange, sFuncStrlen, sFuncStrcmp, sFuncMemcmp, sFuncStrncmp, sFuncWcslen, sFuncWcscmp, sFuncEvent_inject_error_code, sFuncMemcpy, sFuncMemcpy_pa, sFuncWcsncmp, sFuncStruct_forward_declaration, sFuncStruct_definition_begin, sFuncStruct_definition_end, sFuncStruct_variable_declaration, sFuncStruct_member_declaration, sFuncTypedef_declaration, sFuncStruct_pointer, sFuncStruct_array_dimension, sFuncStruct_declarator_complete, sFuncTyped_load, sFuncTyped_store, sFuncAggregate_copy, sFuncAggregate_zero, sFuncStruct_initializer_begin, sFuncStruct_initializer_end, sFuncStruct_pointer_cast, sFuncMember_address, sFuncMember_read, sFuncMember_dot_lvalue, sFuncMember_arrow_lvalue, sFuncMember_dot_read, sFuncMember_arrow_read, sFuncMov_float, sFuncNeg_float, sFuncAdd_float, sFuncSub_float, sFuncMul_float, sFuncDiv_float, sFuncGt_float, sFuncLt_float, sFuncEgt_float, sFuncElt_float, sFuncEqual_float, sFuncNeq_float, sFuncConvert_float, sFuncCast_scalar, sFuncAdd_typed, sFuncSub_typed, sFuncMul_typed, sFuncDiv_typed, sFuncMod_typed, sFuncBitwise_and_typed, sFuncBitwise_or_typed, sFuncBitwise_xor_typed, sFuncShift_left_typed, sFuncShift_right_typed, sFuncGt_typed, sFuncLt_typed, sFuncEgt_typed, sFuncElt_typed, sFuncEqual_typed, sFuncNeq_typed, sFuncNeg_typed, sFuncBitwise_not_typed, sFuncLogical_not_typed, sFuncPointer_diff = Value
}
}

View file

@ -121,6 +121,18 @@ main(int argc, char * argv[])
printf("\n[x] The script floating-point test cases failed\n");
}
}
else if (!strcmp(argv[1], TEST_CASE_PARAMETER_FOR_SCRIPT_VARIABLE_TYPES))
{
if (TestScriptEngineVariableTypes())
{
printf("\n[*] The script variable-type test cases passed successfully\n");
TestResult = TRUE;
}
else
{
printf("\n[x] The script variable-type test cases failed\n");
}
}
else
{
printf("unknown test case\n");

View file

@ -0,0 +1,163 @@
/**
* @file test-script-variable-types.cpp
* @brief Focused parser, IR, and evaluator tests for scalar variable types.
*/
#include "pch.h"
static std::string CapturedVariableTypeOutput;
static VOID
CaptureVariableTypeOutput(CHAR * Message)
{
if (Message)
CapturedVariableTypeOutput.append(Message);
}
static BOOLEAN
RunVariableTypeScript(const CHAR * Script, const CHAR * ExpectedOutput)
{
CapturedVariableTypeOutput.clear();
hyperdbg_u_set_text_message_callback((PVOID)CaptureVariableTypeOutput);
BOOLEAN Result = hyperdbg_u_test_script_engine((CHAR *)Script);
hyperdbg_u_unset_text_message_callback();
if (!Result || CapturedVariableTypeOutput != ExpectedOutput)
{
std::cerr << "Variable-type script failed: " << Script
<< "\nExpected: " << ExpectedOutput
<< "\nActual: " << CapturedVariableTypeOutput << std::endl;
PSYMBOL_BUFFER Buffer = (PSYMBOL_BUFFER)ScriptEngineParse((CHAR *)Script);
if (Buffer && !Buffer->Message)
{
for (UINT32 Index = 0; Index < Buffer->Pointer; Index++)
{
std::cerr << Index << ": type=" << Buffer->Head[Index].Type
<< " len=" << Buffer->Head[Index].Len
<< " value=" << Buffer->Head[Index].Value << std::endl;
}
}
if (Buffer) RemoveSymbolBuffer(Buffer);
return FALSE;
}
return TRUE;
}
static BOOLEAN
RunVariableTypeScriptExpectFailure(const CHAR * Script)
{
CapturedVariableTypeOutput.clear();
hyperdbg_u_set_text_message_callback((PVOID)CaptureVariableTypeOutput);
BOOLEAN Result = hyperdbg_u_test_script_engine((CHAR *)Script);
hyperdbg_u_unset_text_message_callback();
if (Result)
{
std::cerr << "Variable-type script unexpectedly succeeded: " << Script << std::endl;
return FALSE;
}
return TRUE;
}
static BOOLEAN
TestVariableTypeIrContract()
{
if (sizeof(SYMBOL) != sizeof(UINT64) * 3 ||
FUNC_CONVERT_FLOAT != 141 || FUNC_CAST_SCALAR != 142 ||
FUNC_ADD_TYPED != 143 || FUNC_NEQ_TYPED != 158 ||
FUNC_NEG_TYPED != 159 || FUNC_BITWISE_NOT_TYPED != 160 ||
FUNC_LOGICAL_NOT_TYPED != 161 || FUNC_POINTER_DIFF != 162 ||
SCRIPT_SCALAR_TYPE_INVALID != 0 || SCRIPT_SCALAR_TYPE_BOOL != 1 ||
SCRIPT_SCALAR_TYPE_I8 != 2 || SCRIPT_SCALAR_TYPE_I16 != 3 ||
SCRIPT_SCALAR_TYPE_I32 != 4 || SCRIPT_SCALAR_TYPE_I64 != 5 ||
SCRIPT_SCALAR_TYPE_U8 != 6 || SCRIPT_SCALAR_TYPE_U16 != 7 ||
SCRIPT_SCALAR_TYPE_U32 != 8 || SCRIPT_SCALAR_TYPE_U64 != 9 ||
SCRIPT_SCALAR_TYPE_F32 != 10 || SCRIPT_SCALAR_TYPE_F64 != 11 ||
SCRIPT_SCALAR_TYPE_POINTER != 12 || SCRIPT_SCALAR_TYPE_F80 != 13)
{
std::cerr << "Variable-type serialized IR constants changed unexpectedly" << std::endl;
return FALSE;
}
CHAR Script[] = "{ unsigned char narrowValue = 0x12345; int value = narrowValue + 1; value %= 4; }";
PSYMBOL_BUFFER Buffer = (PSYMBOL_BUFFER)ScriptEngineParse(Script);
if (!Buffer || Buffer->Message)
{
std::cerr << "Variable-type IR script did not parse: "
<< (Buffer && Buffer->Message ? Buffer->Message : "no buffer") << std::endl;
if (Buffer) RemoveSymbolBuffer(Buffer);
return FALSE;
}
BOOLEAN SawCast = FALSE;
BOOLEAN SawAdd = FALSE;
BOOLEAN SawModulo = FALSE;
for (UINT32 Index = 0; Index < Buffer->Pointer; Index++)
{
if (Buffer->Head[Index].Type != SYMBOL_SEMANTIC_RULE_TYPE)
continue;
SawCast |= Buffer->Head[Index].Value == FUNC_CAST_SCALAR;
SawAdd |= Buffer->Head[Index].Value == FUNC_ADD_TYPED;
SawModulo |= Buffer->Head[Index].Value == FUNC_MOD_TYPED;
}
RemoveSymbolBuffer(Buffer);
if (!SawCast || !SawAdd || !SawModulo)
{
std::cerr << "Variable-type IR is missing cast/add/modulo: "
<< SawCast << "/" << SawAdd << "/" << SawModulo << std::endl;
}
return SawCast && SawAdd && SawModulo;
}
BOOLEAN
TestScriptEngineVariableTypes()
{
return TestVariableTypeIrContract() &&
RunVariableTypeScript("{ char narrow = 0xff; unsigned char narrowValue = 0x12345; int promoted = narrowValue; printf(\"%lld %lld %lld\\n\", narrow, narrowValue, promoted); }",
"-1 69 69\n") &&
RunVariableTypeScript("{ int value = 0n10; value %= 4; long wide = 0n10; wide %= 4; printf(\"%lld %lld\\n\", value, wide); }",
"2 2\n") &&
RunVariableTypeScript("{ printf(\"%lld %lld %lld %lld %lld\\n\", sizeof(char), sizeof(short), sizeof(int), sizeof(long), sizeof(long long)); }",
"1 2 4 8 8\n") &&
RunVariableTypeScript("{ printf(\"%lld %lld\\n\", sizeof(!(char)0), sizeof(!(long)0)); }",
"4 4\n") &&
RunVariableTypeScript("{ if (sizeof(char) == 1 && (int)1 == 1) { printf(\"boolean type syntax\\n\"); } }",
"boolean type syntax\n") &&
RunVariableTypeScript("{ struct Pair { int left; unsigned short right; }; printf(\"%lld\\n\", sizeof(struct Pair)); }",
"8\n") &&
RunVariableTypeScript("{ struct NarrowFields { char signedValue; unsigned char unsignedValue; }; struct NarrowFields fields; fields.signedValue = 0xff; fields.unsignedValue = 0x1ff; printf(\"%lld %lld\\n\", fields.signedValue, fields.unsignedValue); }",
"-1 255\n") &&
RunVariableTypeScript("{ struct CompoundFields { int signedValue; unsigned char unsignedValue; }; struct CompoundFields fields; fields.signedValue = 0n10; fields.signedValue %= 4; fields.unsignedValue = 0x105; fields.unsignedValue += 0x100; printf(\"%lld %lld\\n\", fields.signedValue, fields.unsignedValue); }",
"2 5\n") &&
RunVariableTypeScript("{ char values[2] = {0xff, 0x7f}; printf(\"%lld %lld\\n\", values[0], values[1]); }",
"-1 127\n") &&
RunVariableTypeScript("{ typedef unsigned short word; word value = 0x12345; printf(\"%lld %lld\\n\", value, sizeof(word)); }",
"9029 2\n") &&
RunVariableTypeScript("{ int probe() { printf(\"evaluated\\n\"); return 1; } printf(\"%lld\\n\", sizeof(probe())); }",
"4\n") &&
RunVariableTypeScript("{ int add_to_55(int value) { return 0n55 + value; } result = add_to_55(0n47); printf(\"%lld\\n\", result); }",
"102\n") &&
RunVariableTypeScript("{ int typed_factorial(int value) { if (value == 0 || value == 1) { return 1; } return value * typed_factorial(value - 1); } result = typed_factorial(0n10); printf(\"%lld\\n\", result); }",
"3628800\n") &&
RunVariableTypeScript("{ source_value = 0n123456; destination_value = 0; memcpy(&destination_value, &source_value, 8); printf(\"%lld\\n\", destination_value); }",
"123456\n") &&
RunVariableTypeScript("{ local_value = 0n55; result = &local_value; printf(\"%lld %lld\\n\", sizeof(result), dq(result)); }",
"8 55\n") &&
RunVariableTypeScript("{ .global_value = 0n55; result = &(.global_value); printf(\"%lld %lld\\n\", sizeof(result), dq(result)); }",
"8 55\n") &&
RunVariableTypeScript("{ char narrow_value = 0x7f; char *narrow_pointer = &narrow_value; printf(\"%lld\\n\", *narrow_pointer); }",
"127\n") &&
RunVariableTypeScript("{ int integerValue = (int)(unsigned char)0x12345; double doubleValue = (double)integerValue; long restored = (long)doubleValue; printf(\"%lld %f %lld\\n\", integerValue, doubleValue, restored); }",
"69 69.000000 69\n") &&
RunVariableTypeScript("{ char *left = (char *)0xffffffffffffffff; char *right = (char *)0xfffffffffffffff0; if (left > right) { printf(\"%lld %lld 1\\n\", left - right, right - left); } }",
"15 -15 1\n") &&
RunVariableTypeScript("{ char *base = (char *)0x1000; char *next = base + 0n2; printf(\"%lld\\n\", next - base); }",
"2\n") &&
RunVariableTypeScript("{ if (1 || 1 / 0) { printf(\"or short circuit\\n\"); } if (0 && 1 / 0) { printf(\"unexpected\\n\"); } printf(\"and short circuit\\n\"); }",
"or short circuit\nand short circuit\n") &&
RunVariableTypeScript("{ inferred = 0xffffffffffffffff; printf(\"%llu %lld\\n\", inferred, sizeof(inferred)); }",
"18446744073709551615 8\n") &&
RunVariableTypeScriptExpectFailure("{ unsigned float invalidValue = 1.0; }") &&
RunVariableTypeScriptExpectFailure("{ long double invalidValue = 1.0; }") &&
RunVariableTypeScriptExpectFailure("{ long long long invalidValue = 1; }") &&
RunVariableTypeScriptExpectFailure("{ local_value = 0n55; unsigned long long explicit_result = &local_value; }") &&
RunVariableTypeScriptExpectFailure("{ int value = 1; value = value / 0; }") &&
RunVariableTypeScriptExpectFailure("{ unsigned long value = 1; value = value << 0n64; }");
}

View file

@ -16,6 +16,8 @@ namespace fs = std::filesystem;
static std::mutex SemanticOutputMutex;
static std::condition_variable SemanticOutputChanged;
static std::string SemanticOutput;
static std::set<UINT32> ExpectedSemanticCases;
static std::set<std::string> ExpectedSemanticMarkers;
static VOID
CaptureSemanticOutput(CHAR * Message)
@ -49,17 +51,20 @@ HasAllExpectedSemanticOutput(const std::string & Output)
SuccessfulCases.insert((UINT32)std::stoul((*Match)[1].str()));
}
return SuccessfulCases.size() == 83 &&
*SuccessfulCases.begin() == 0 &&
*SuccessfulCases.rbegin() == 82 &&
Output.find("floating point: 11.500000 0.500000 0.500000 11.000000 0.789000") != std::string::npos &&
Output.find("negative floating point: -11.500000 -0.500000 -0.789000 -0.000000") != std::string::npos &&
Output.find("runtime negative floating point: -0.789000") != std::string::npos &&
Output.find("runtime positive floating point: 0.500000") != std::string::npos &&
Output.find("floating arithmetic was successful") != std::string::npos &&
Output.find("floating arithmetic: 12.000000 11.000000 3.000000 3.000000") != std::string::npos &&
Output.find("double arithmetic: 1.000000 3.500000 5.000000 2.250000") != std::string::npos &&
Output.find("mixed and precedence: 1.750000 7.000000 -6.000000") != std::string::npos;
if (SuccessfulCases != ExpectedSemanticCases)
{
return FALSE;
}
for (const std::string & Marker : ExpectedSemanticMarkers)
{
if (Output.find(Marker) == std::string::npos)
{
return FALSE;
}
}
return !ExpectedSemanticCases.empty() || !ExpectedSemanticMarkers.empty();
}
static BOOLEAN
@ -99,6 +104,12 @@ ReadDirectoryAndTestSemanticTestCases(const CHAR * ScriptSemanticPath)
return FALSE;
}
ExpectedSemanticCases.clear();
ExpectedSemanticMarkers.clear();
const std::regex CasePattern("test_case([0-9]+)[[:space:]]*=[[:space:]]*1");
const std::regex MarkerPattern("//[[:space:]]*semantic-test-marker:[[:space:]]*([^\\r\\n]+)");
for (const auto & FilePath : TestFiles)
{
std::ifstream File(FilePath, std::ios::binary);
@ -116,6 +127,28 @@ ReadDirectoryAndTestSemanticTestCases(const CHAR * ScriptSemanticPath)
return FALSE;
}
BOOLEAN HasExpectation = FALSE;
for (std::sregex_iterator Match(Content.begin(), Content.end(), CasePattern), End;
Match != End;
++Match)
{
ExpectedSemanticCases.insert((UINT32)std::stoul((*Match)[1].str()));
HasExpectation = TRUE;
}
for (std::sregex_iterator Match(Content.begin(), Content.end(), MarkerPattern), End;
Match != End;
++Match)
{
ExpectedSemanticMarkers.insert((*Match)[1].str());
HasExpectation = TRUE;
}
if (!HasExpectation)
{
std::cerr << "Semantic file has no enabled numbered case or semantic-test-marker: "
<< FilePath.string() << std::endl;
return FALSE;
}
std::cout << "Executing file " << FilePath.filename().string() << std::endl;
if (hyperdbg_u_run_command(Content.data()) != 0)
{

View file

@ -30,4 +30,5 @@ TestSemanticScripts();
BOOLEAN
TestScriptEngineFloatingPoint();
#define TEST_CASE_PARAMETER_FOR_SCRIPT_FLOATING_POINT "test-script-floating-point"
BOOLEAN
TestScriptEngineVariableTypes();

View file

@ -114,6 +114,7 @@
<ClCompile Include="code\tests\test-parser.cpp" />
<ClCompile Include="code\tests\test-semantic-scripts.cpp" />
<ClCompile Include="code\tests\test-script-floating-point.cpp" />
<ClCompile Include="code\tests\test-script-variable-types.cpp" />
<ClCompile Include="code\tools.cpp" />
<ClCompile Include="pch.cpp" />
</ItemGroup>

View file

@ -70,6 +70,21 @@ typedef struct ACTION_BUFFER {
#define SCRIPT_ENGINE_ADDRESS_SPACE_LOCAL 1
#define SCRIPT_ENGINE_ADDRESS_SPACE_REMOTE 2
#define SCRIPT_SCALAR_TYPE_INVALID 0
#define SCRIPT_SCALAR_TYPE_BOOL 1
#define SCRIPT_SCALAR_TYPE_I8 2
#define SCRIPT_SCALAR_TYPE_I16 3
#define SCRIPT_SCALAR_TYPE_I32 4
#define SCRIPT_SCALAR_TYPE_I64 5
#define SCRIPT_SCALAR_TYPE_U8 6
#define SCRIPT_SCALAR_TYPE_U16 7
#define SCRIPT_SCALAR_TYPE_U32 8
#define SCRIPT_SCALAR_TYPE_U64 9
#define SCRIPT_SCALAR_TYPE_F32 10
#define SCRIPT_SCALAR_TYPE_F64 11
#define SCRIPT_SCALAR_TYPE_POINTER 12
#define SCRIPT_SCALAR_TYPE_F80 13
static const char *const SymbolTypeNames[] = {
"SYMBOL_UNDEFINED",
"SYMBOL_GLOBAL_ID_TYPE",
@ -243,6 +258,27 @@ static const char *const SymbolTypeNames[] = {
#define FUNC_EQUAL_FLOAT 139
#define FUNC_NEQ_FLOAT 140
#define FUNC_CONVERT_FLOAT 141
#define FUNC_CAST_SCALAR 142
#define FUNC_ADD_TYPED 143
#define FUNC_SUB_TYPED 144
#define FUNC_MUL_TYPED 145
#define FUNC_DIV_TYPED 146
#define FUNC_MOD_TYPED 147
#define FUNC_BITWISE_AND_TYPED 148
#define FUNC_BITWISE_OR_TYPED 149
#define FUNC_BITWISE_XOR_TYPED 150
#define FUNC_SHIFT_LEFT_TYPED 151
#define FUNC_SHIFT_RIGHT_TYPED 152
#define FUNC_GT_TYPED 153
#define FUNC_LT_TYPED 154
#define FUNC_EGT_TYPED 155
#define FUNC_ELT_TYPED 156
#define FUNC_EQUAL_TYPED 157
#define FUNC_NEQ_TYPED 158
#define FUNC_NEG_TYPED 159
#define FUNC_BITWISE_NOT_TYPED 160
#define FUNC_LOGICAL_NOT_TYPED 161
#define FUNC_POINTER_DIFF 162
static const char *const FunctionNames[] = {
"FUNC_UNDEFINED",
@ -387,6 +423,27 @@ static const char *const FunctionNames[] = {
"FUNC_EQUAL_FLOAT",
"FUNC_NEQ_FLOAT",
"FUNC_CONVERT_FLOAT",
"FUNC_CAST_SCALAR",
"FUNC_ADD_TYPED",
"FUNC_SUB_TYPED",
"FUNC_MUL_TYPED",
"FUNC_DIV_TYPED",
"FUNC_MOD_TYPED",
"FUNC_BITWISE_AND_TYPED",
"FUNC_BITWISE_OR_TYPED",
"FUNC_BITWISE_XOR_TYPED",
"FUNC_SHIFT_LEFT_TYPED",
"FUNC_SHIFT_RIGHT_TYPED",
"FUNC_GT_TYPED",
"FUNC_LT_TYPED",
"FUNC_EGT_TYPED",
"FUNC_ELT_TYPED",
"FUNC_EQUAL_TYPED",
"FUNC_NEQ_TYPED",
"FUNC_NEG_TYPED",
"FUNC_BITWISE_NOT_TYPED",
"FUNC_LOGICAL_NOT_TYPED",
"FUNC_POINTER_DIFF",
};
typedef enum REGS_ENUM {

View file

@ -93,6 +93,8 @@
* @brief Test case parameter for testing semantic script tests
*/
#define TEST_CASE_PARAMETER_FOR_SCRIPT_SEMANTIC_TEST_CASES "test-script-semantic-test-cases"
#define TEST_CASE_PARAMETER_FOR_SCRIPT_FLOATING_POINT "test-script-floating-point"
#define TEST_CASE_PARAMETER_FOR_SCRIPT_VARIABLE_TYPES "test-script-variable-types"
/**
* @brief Test cases file name

View file

@ -134,6 +134,18 @@ CommandTestAllFunctionalities()
return;
}
if (!OpenHyperDbgTestProcess(&ThreadHandle, &ProcessHandle, (CHAR *)TEST_CASE_PARAMETER_FOR_SCRIPT_FLOATING_POINT))
{
ShowMessages("err, start HyperDbg test process for testing floating-point scripts\n");
return;
}
if (!OpenHyperDbgTestProcess(&ThreadHandle, &ProcessHandle, (CHAR *)TEST_CASE_PARAMETER_FOR_SCRIPT_VARIABLE_TYPES))
{
ShowMessages("err, start HyperDbg test process for testing variable-type scripts\n");
return;
}
//
// Test script engine (script parser) using semantic tests
//

View file

@ -56,6 +56,7 @@ NewUnknownToken()
Token->VariableMemoryIdx = 0;
Token->AddressSpace = 0;
Token->IsAddress = FALSE;
Token->IsImplicitType = FALSE;
return Token;
}
@ -95,6 +96,7 @@ NewToken(SCRIPT_ENGINE_TOKEN_TYPE Type, char * Value)
Token->VariableMemoryIdx = 0;
Token->AddressSpace = 0;
Token->IsAddress = FALSE;
Token->IsImplicitType = FALSE;
if (Token->Value == NULL)
{
@ -347,6 +349,7 @@ CopyToken(PSCRIPT_ENGINE_TOKEN Token)
TokenCopy->VariableMemoryIdx = Token->VariableMemoryIdx;
TokenCopy->AddressSpace = Token->AddressSpace;
TokenCopy->IsAddress = Token->IsAddress;
TokenCopy->IsImplicitType = Token->IsImplicitType;
if (TokenCopy->Value == NULL)
{
@ -1295,6 +1298,13 @@ LalrGetTerminalId(PSCRIPT_ENGINE_TOKEN Token)
return i;
}
}
else if (Token->Type == SCRIPT_VARIABLE_TYPE)
{
if (!strcmp("_script_variable_type", LalrTerminalMap[i]))
{
return i;
}
}
else if (Token->Type == REGISTER)
{
if (!strcmp("_register", LalrTerminalMap[i]))

File diff suppressed because it is too large Load diff

View file

@ -318,7 +318,7 @@ GetToken(char * c, char * str)
else
{
strcpy(Token->Value, "!");
Token->Type = UNKNOWN;
Token->Type = SPECIAL_TOKEN;
return Token;
}
case '%':
@ -541,6 +541,7 @@ GetToken(char * c, char * str)
{
Token->Type = GLOBAL_ID;
Token->VariableType = GetGlobalIdentifierVariableType(Token);
Token->IsImplicitType = GetGlobalIdentifierIsImplicitType(Token);
}
else
{
@ -827,6 +828,10 @@ GetToken(char * c, char * str)
{
Token->Type = SCRIPT_VARIABLE_TYPE;
}
else if ((Token->VariableType = FindTypedefType(Token->Value)) != NULL)
{
Token->Type = SCRIPT_VARIABLE_TYPE;
}
else
{
BOOLEAN WasFound = FALSE;
@ -866,6 +871,7 @@ GetToken(char * c, char * str)
{
Token->Type = LOCAL_ID;
Token->VariableType = GetLocalIdentifierVariableType(Token);
Token->IsImplicitType = GetLocalIdentifierIsImplicitType(Token);
}
else
{
@ -890,6 +896,10 @@ GetToken(char * c, char * str)
{
Token->Type = SCRIPT_VARIABLE_TYPE;
}
else if ((Token->VariableType = FindTypedefType(Token->Value)) != NULL)
{
Token->Type = SCRIPT_VARIABLE_TYPE;
}
else if (IsId(Token->Value))
{
BOOLEAN WasFound = FALSE;
@ -929,6 +939,7 @@ GetToken(char * c, char * str)
{
Token->Type = LOCAL_ID;
Token->VariableType = GetLocalIdentifierVariableType(Token);
Token->IsImplicitType = GetLocalIdentifierIsImplicitType(Token);
}
else
{
@ -965,6 +976,10 @@ GetToken(char * c, char * str)
{
Token->Type = SCRIPT_VARIABLE_TYPE;
}
else if ((Token->VariableType = FindTypedefType(Token->Value)) != NULL)
{
Token->Type = SCRIPT_VARIABLE_TYPE;
}
else
{
BOOLEAN WasFound = FALSE;
@ -1004,6 +1019,7 @@ GetToken(char * c, char * str)
{
Token->Type = LOCAL_ID;
Token->VariableType = GetLocalIdentifierVariableType(Token);
Token->IsImplicitType = GetLocalIdentifierIsImplicitType(Token);
}
else
{

File diff suppressed because it is too large Load diff

View file

@ -320,24 +320,40 @@ AddTypedefType(const char * Name, PVARIABLE_TYPE Type)
return TRUE;
}
VARIABLE_TYPE * VARIABLE_TYPE_UNKNOWN = &(VARIABLE_TYPE) {TY_UNKNOWN};
PVARIABLE_TYPE
FindTypedefType(const char * Name)
{
PTYPEDEF_NODE Node;
for (Node = Typedefs; Node; Node = Node->Next)
{
if (!strcmp(Node->Name, Name))
{
return Node->Type;
}
}
return NULL;
}
VARIABLE_TYPE * VARIABLE_TYPE_VOID = &(VARIABLE_TYPE) {TY_VOID, 1, 1};
VARIABLE_TYPE * VARIABLE_TYPE_BOOL = &(VARIABLE_TYPE) {TY_BOOL, 1, 1};
VARIABLE_TYPE * VARIABLE_TYPE_UNKNOWN = &(VARIABLE_TYPE) {.Kind = TY_UNKNOWN};
VARIABLE_TYPE * VARIABLE_TYPE_CHAR = &(VARIABLE_TYPE) {TY_CHAR, 1, 1};
VARIABLE_TYPE * VARIABLE_TYPE_SHORT = &(VARIABLE_TYPE) {TY_SHORT, 2, 2};
VARIABLE_TYPE * VARIABLE_TYPE_INT = &(VARIABLE_TYPE) {TY_INT, 4, 4};
VARIABLE_TYPE * VARIABLE_TYPE_LONG = &(VARIABLE_TYPE) {TY_LONG, 8, 8};
VARIABLE_TYPE * VARIABLE_TYPE_VOID = &(VARIABLE_TYPE) {.Kind = TY_VOID, .Size = 1, .Align = 1, .IsComplete = TRUE};
VARIABLE_TYPE * VARIABLE_TYPE_BOOL = &(VARIABLE_TYPE) {.Kind = TY_BOOL, .Size = 1, .Align = 1, .IsComplete = TRUE, .IntegerRank = INTEGER_RANK_BOOL};
VARIABLE_TYPE * VARIABLE_TYPE_UCHAR = &(VARIABLE_TYPE) {TY_CHAR, 1, 1, TRUE};
VARIABLE_TYPE * VARIABLE_TYPE_USHORT = &(VARIABLE_TYPE) {TY_SHORT, 2, 2, TRUE};
VARIABLE_TYPE * VARIABLE_TYPE_UINT = &(VARIABLE_TYPE) {TY_INT, 4, 4, TRUE};
VARIABLE_TYPE * VARIABLE_TYPE_ULONG = &(VARIABLE_TYPE) {TY_LONG, 8, 8, TRUE};
VARIABLE_TYPE * VARIABLE_TYPE_CHAR = &(VARIABLE_TYPE) {.Kind = TY_CHAR, .Size = 1, .Align = 1, .IsComplete = TRUE, .IntegerRank = INTEGER_RANK_CHAR};
VARIABLE_TYPE * VARIABLE_TYPE_SHORT = &(VARIABLE_TYPE) {.Kind = TY_SHORT, .Size = 2, .Align = 2, .IsComplete = TRUE, .IntegerRank = INTEGER_RANK_SHORT};
VARIABLE_TYPE * VARIABLE_TYPE_INT = &(VARIABLE_TYPE) {.Kind = TY_INT, .Size = 4, .Align = 4, .IsComplete = TRUE, .IntegerRank = INTEGER_RANK_INT};
VARIABLE_TYPE * VARIABLE_TYPE_LONG = &(VARIABLE_TYPE) {.Kind = TY_LONG, .Size = 8, .Align = 8, .IsComplete = TRUE, .IntegerRank = INTEGER_RANK_LONG};
VARIABLE_TYPE * VARIABLE_TYPE_LLONG = &(VARIABLE_TYPE) {.Kind = TY_LLONG, .Size = 8, .Align = 8, .IsComplete = TRUE, .IntegerRank = INTEGER_RANK_LONG_LONG};
VARIABLE_TYPE * VARIABLE_TYPE_FLOAT = &(VARIABLE_TYPE) {TY_FLOAT, 4, 4};
VARIABLE_TYPE * VARIABLE_TYPE_DOUBLE = &(VARIABLE_TYPE) {TY_DOUBLE, 8, 8};
VARIABLE_TYPE * VARIABLE_TYPE_LDOUBLE = &(VARIABLE_TYPE) {TY_LDOUBLE, 16, 16};
VARIABLE_TYPE * VARIABLE_TYPE_UCHAR = &(VARIABLE_TYPE) {.Kind = TY_CHAR, .Size = 1, .Align = 1, .IsUnsigned = TRUE, .IsComplete = TRUE, .IntegerRank = INTEGER_RANK_CHAR};
VARIABLE_TYPE * VARIABLE_TYPE_USHORT = &(VARIABLE_TYPE) {.Kind = TY_SHORT, .Size = 2, .Align = 2, .IsUnsigned = TRUE, .IsComplete = TRUE, .IntegerRank = INTEGER_RANK_SHORT};
VARIABLE_TYPE * VARIABLE_TYPE_UINT = &(VARIABLE_TYPE) {.Kind = TY_INT, .Size = 4, .Align = 4, .IsUnsigned = TRUE, .IsComplete = TRUE, .IntegerRank = INTEGER_RANK_INT};
VARIABLE_TYPE * VARIABLE_TYPE_ULONG = &(VARIABLE_TYPE) {.Kind = TY_LONG, .Size = 8, .Align = 8, .IsUnsigned = TRUE, .IsComplete = TRUE, .IntegerRank = INTEGER_RANK_LONG};
VARIABLE_TYPE * VARIABLE_TYPE_ULLONG = &(VARIABLE_TYPE) {.Kind = TY_LLONG, .Size = 8, .Align = 8, .IsUnsigned = TRUE, .IsComplete = TRUE, .IntegerRank = INTEGER_RANK_LONG_LONG};
VARIABLE_TYPE * VARIABLE_TYPE_FLOAT = &(VARIABLE_TYPE) {.Kind = TY_FLOAT, .Size = 4, .Align = 4, .IsComplete = TRUE};
VARIABLE_TYPE * VARIABLE_TYPE_DOUBLE = &(VARIABLE_TYPE) {.Kind = TY_DOUBLE, .Size = 8, .Align = 8, .IsComplete = TRUE};
VARIABLE_TYPE * VARIABLE_TYPE_LDOUBLE = &(VARIABLE_TYPE) {.Kind = TY_LDOUBLE, .Size = 16, .Align = 16, .IsComplete = TRUE};
/**
* @brief Return a variable type based on the token stack
@ -348,23 +364,10 @@ VARIABLE_TYPE * VARIABLE_TYPE_LDOUBLE = &(VARIABLE_TYPE) {TY_LDOUBLE, 16, 16};
VARIABLE_TYPE *
HandleType(PSCRIPT_ENGINE_TOKEN_LIST PtokenStack)
{
enum
{
ENUM_VOID = 1 << 0,
ENUM_BOOL = 1 << 2,
ENUM_CHAR = 1 << 4,
ENUM_SHORT = 1 << 6,
ENUM_INT = 1 << 8,
ENUM_LONG = 1 << 10,
ENUM_FLOAT = 1 << 12,
ENUM_DOUBLE = 1 << 14,
ENUM_OTHER = 1 << 16,
ENUM_SIGNED = 1 << 17,
ENUM_UNSIGNED = 1 << 18,
};
VARIABLE_TYPE * Result = VARIABLE_TYPE_UNKNOWN;
int Counter = 0;
unsigned int VoidCount = 0, BoolCount = 0, CharCount = 0;
unsigned int ShortCount = 0, IntCount = 0, LongCount = 0;
unsigned int FloatCount = 0, DoubleCount = 0;
unsigned int SignedCount = 0, UnsignedCount = 0;
PSCRIPT_ENGINE_TOKEN TopToken = NULL;
while (PtokenStack->Pointer > 0)
@ -375,114 +378,102 @@ HandleType(PSCRIPT_ENGINE_TOKEN_LIST PtokenStack)
Push(PtokenStack, TopToken);
break;
}
{
PVARIABLE_TYPE TypedefType = FindTypedefType(TopToken->Value);
if (TypedefType)
{
RemoveToken(&TopToken);
if (VoidCount || BoolCount || CharCount || ShortCount || IntCount || LongCount ||
FloatCount || DoubleCount || SignedCount || UnsignedCount ||
(PtokenStack->Pointer && Top(PtokenStack)->Type == SCRIPT_VARIABLE_TYPE))
return VARIABLE_TYPE_UNKNOWN;
return TypedefType;
}
}
if (!strcmp(TopToken->Value, "void"))
{
Counter += ENUM_VOID;
VoidCount++;
}
else if (!strcmp(TopToken->Value, "bool"))
{
Counter += ENUM_BOOL;
BoolCount++;
}
else if (!strcmp(TopToken->Value, "char"))
{
Counter += ENUM_CHAR;
CharCount++;
}
else if (!strcmp(TopToken->Value, "short"))
{
Counter += ENUM_SHORT;
ShortCount++;
}
else if (!strcmp(TopToken->Value, "int"))
{
Counter += ENUM_INT;
IntCount++;
}
else if (!strcmp(TopToken->Value, "long"))
{
Counter += ENUM_LONG;
LongCount++;
}
else if (!strcmp(TopToken->Value, "float"))
{
Counter += ENUM_FLOAT;
FloatCount++;
}
else if (!strcmp(TopToken->Value, "double"))
{
Counter += ENUM_DOUBLE;
DoubleCount++;
}
else if (!strcmp(TopToken->Value, "signed"))
{
Counter |= ENUM_SIGNED;
SignedCount++;
}
else if (!strcmp(TopToken->Value, "unsigned"))
{
Counter |= ENUM_UNSIGNED;
UnsignedCount++;
}
else
{
return VARIABLE_TYPE_UNKNOWN;
}
RemoveToken(&TopToken);
switch (Counter)
{
case ENUM_VOID:
Result = VARIABLE_TYPE_VOID;
break;
case ENUM_BOOL:
Result = VARIABLE_TYPE_BOOL;
break;
case ENUM_CHAR:
case ENUM_SIGNED + ENUM_CHAR:
Result = VARIABLE_TYPE_CHAR;
break;
case ENUM_UNSIGNED + ENUM_CHAR:
Result = VARIABLE_TYPE_UCHAR;
break;
case ENUM_SHORT:
case ENUM_SHORT + ENUM_INT:
case ENUM_SIGNED + ENUM_SHORT:
case ENUM_SIGNED + ENUM_SHORT + ENUM_INT:
Result = VARIABLE_TYPE_INT;
break;
case ENUM_UNSIGNED + ENUM_SHORT:
case ENUM_UNSIGNED + ENUM_SHORT + ENUM_INT:
Result = VARIABLE_TYPE_USHORT;
break;
case ENUM_INT:
case ENUM_SIGNED:
case ENUM_SIGNED + ENUM_INT:
Result = VARIABLE_TYPE_INT;
break;
case ENUM_UNSIGNED:
case ENUM_UNSIGNED + ENUM_INT:
Result = VARIABLE_TYPE_UINT;
break;
case ENUM_LONG:
case ENUM_LONG + ENUM_INT:
case ENUM_LONG + ENUM_LONG:
case ENUM_LONG + ENUM_LONG + ENUM_INT:
case ENUM_SIGNED + ENUM_LONG:
case ENUM_SIGNED + ENUM_LONG + ENUM_INT:
case ENUM_SIGNED + ENUM_LONG + ENUM_LONG:
case ENUM_SIGNED + ENUM_LONG + ENUM_LONG + ENUM_INT:
Result = VARIABLE_TYPE_LONG;
break;
case ENUM_UNSIGNED + ENUM_LONG:
case ENUM_UNSIGNED + ENUM_LONG + ENUM_INT:
case ENUM_UNSIGNED + ENUM_LONG + ENUM_LONG:
case ENUM_UNSIGNED + ENUM_LONG + ENUM_LONG + ENUM_INT:
Result = VARIABLE_TYPE_ULONG;
break;
case ENUM_FLOAT:
Result = VARIABLE_TYPE_FLOAT;
break;
case ENUM_DOUBLE:
Result = VARIABLE_TYPE_DOUBLE;
break;
case ENUM_LONG + ENUM_DOUBLE:
Result = VARIABLE_TYPE_LDOUBLE;
break;
}
}
return Result;
if (SignedCount > 1 || UnsignedCount > 1 || (SignedCount && UnsignedCount) ||
VoidCount > 1 || BoolCount > 1 || CharCount > 1 || ShortCount > 1 ||
IntCount > 1 || LongCount > 2 || FloatCount > 1 || DoubleCount > 1)
{
return VARIABLE_TYPE_UNKNOWN;
}
if (VoidCount || BoolCount || CharCount || ShortCount || FloatCount || DoubleCount)
{
if (VoidCount && !(BoolCount || CharCount || ShortCount || IntCount || LongCount || FloatCount || DoubleCount || SignedCount || UnsignedCount))
return VARIABLE_TYPE_VOID;
if (BoolCount && !(VoidCount || CharCount || ShortCount || IntCount || LongCount || FloatCount || DoubleCount || SignedCount || UnsignedCount))
return VARIABLE_TYPE_BOOL;
if (CharCount && !(VoidCount || BoolCount || ShortCount || IntCount || LongCount || FloatCount || DoubleCount))
return UnsignedCount ? VARIABLE_TYPE_UCHAR : VARIABLE_TYPE_CHAR;
if (ShortCount && !(VoidCount || BoolCount || CharCount || LongCount || FloatCount || DoubleCount))
return UnsignedCount ? VARIABLE_TYPE_USHORT : VARIABLE_TYPE_SHORT;
if (FloatCount && !(VoidCount || BoolCount || CharCount || ShortCount || IntCount || LongCount || DoubleCount || SignedCount || UnsignedCount))
return VARIABLE_TYPE_FLOAT;
if (DoubleCount && !VoidCount && !BoolCount && !CharCount && !ShortCount && !IntCount && !FloatCount && !SignedCount && !UnsignedCount)
return LongCount == 0 ? VARIABLE_TYPE_DOUBLE : VARIABLE_TYPE_UNKNOWN;
return VARIABLE_TYPE_UNKNOWN;
}
if (LongCount)
{
if (VoidCount || BoolCount || CharCount || ShortCount || FloatCount || DoubleCount)
return VARIABLE_TYPE_UNKNOWN;
if (LongCount == 2)
return UnsignedCount ? VARIABLE_TYPE_ULLONG : VARIABLE_TYPE_LLONG;
return UnsignedCount ? VARIABLE_TYPE_ULONG : VARIABLE_TYPE_LONG;
}
if (IntCount || SignedCount || UnsignedCount)
return UnsignedCount ? VARIABLE_TYPE_UINT : VARIABLE_TYPE_INT;
return VARIABLE_TYPE_UNKNOWN;
}
/**
@ -495,15 +486,48 @@ HandleType(PSCRIPT_ENGINE_TOKEN_LIST PtokenStack)
VARIABLE_TYPE *
GetCommonVariableType(VARIABLE_TYPE * Ty1, VARIABLE_TYPE * Ty2)
{
// if (Ty1->Kind == TY_ARRAY)
//{
// return Ty1;
// }
PVARIABLE_TYPE LeftType = PromoteIntegerVariableType(Ty1);
PVARIABLE_TYPE RightType = PromoteIntegerVariableType(Ty2);
// if (Ty2->Kind == TY_ARRAY)
//{
// return Ty2;
// }
if (!IsIntegerVariableType(LeftType) || !IsIntegerVariableType(RightType))
return VARIABLE_TYPE_UNKNOWN;
if (LeftType == RightType)
return LeftType;
if (LeftType->IsUnsigned == RightType->IsUnsigned)
return LeftType->IntegerRank >= RightType->IntegerRank ? LeftType : RightType;
return VARIABLE_TYPE_LONG;
PVARIABLE_TYPE UnsignedType = LeftType->IsUnsigned ? LeftType : RightType;
PVARIABLE_TYPE SignedType = LeftType->IsUnsigned ? RightType : LeftType;
if (UnsignedType->IntegerRank >= SignedType->IntegerRank)
return UnsignedType;
if (SignedType->Size > UnsignedType->Size)
return SignedType;
if (SignedType == VARIABLE_TYPE_LONG) return VARIABLE_TYPE_ULONG;
if (SignedType == VARIABLE_TYPE_LLONG) return VARIABLE_TYPE_ULLONG;
return VARIABLE_TYPE_UINT;
}
PVARIABLE_TYPE
GetDefaultImplicitVariableType(VOID)
{
return VARIABLE_TYPE_ULLONG;
}
BOOLEAN
IsIntegerVariableType(PVARIABLE_TYPE Type)
{
return Type && (Type->Kind == TY_BOOL || Type->Kind == TY_CHAR ||
Type->Kind == TY_SHORT || Type->Kind == TY_INT ||
Type->Kind == TY_LONG || Type->Kind == TY_LLONG ||
Type->Kind == TY_ENUM);
}
PVARIABLE_TYPE
PromoteIntegerVariableType(PVARIABLE_TYPE Type)
{
if (!IsIntegerVariableType(Type))
return Type;
if (Type->IntegerRank < INTEGER_RANK_INT)
return VARIABLE_TYPE_INT;
return Type;
}

View file

@ -78,6 +78,7 @@ typedef struct _SCRIPT_ENGINE_TOKEN
unsigned long long VariableMemoryIdx;
unsigned int AddressSpace;
BOOLEAN IsAddress;
BOOLEAN IsImplicitType;
} SCRIPT_ENGINE_TOKEN, *PSCRIPT_ENGINE_TOKEN;
/**

View file

@ -1,9 +1,9 @@
#pragma once
#ifndef PARSE_TABLE_H
#define PARSE_TABLE_H
#define RULES_COUNT 331
#define TERMINAL_COUNT 133
#define NONETERMINAL_COUNT 85
#define RULES_COUNT 355
#define TERMINAL_COUNT 135
#define NONETERMINAL_COUNT 91
#define START_VARIABLE "S"
#define MAX_RHS_LEN 15
#define KEYWORD_LIST_LENGTH 121
@ -13,7 +13,7 @@
#define PSEUDO_REGISTER_MAP_LIST_LENGTH 16
#define SCRIPT_VARIABLE_TYPE_LIST_LENGTH 10
#define ASSIGNMENT_OPERATOR_LIST_LENGTH 10
#define SEMANTIC_RULES_MAP_LIST_LENGTH 201
#define SEMANTIC_RULES_MAP_LIST_LENGTH 211
#define THREEOPFUNC1_LENGTH 1
#define THREEOPFUNC2_LENGTH 3
#define TWOOPFUNC1_LENGTH 8
@ -60,16 +60,16 @@ extern const SYMBOL_MAP PseudoRegisterMapList[];
extern const char* ScriptVariableTypeList[];
#define LALR_RULES_COUNT 121
#define LALR_TERMINAL_COUNT 89
#define LALR_NONTERMINAL_COUNT 27
#define LALR_RULES_COUNT 141
#define LALR_TERMINAL_COUNT 93
#define LALR_NONTERMINAL_COUNT 37
#define LALR_MAX_RHS_LEN 9
#define LALR_STATE_COUNT 338
#define LALR_STATE_COUNT 373
extern const struct _SCRIPT_ENGINE_TOKEN LalrLhs[RULES_COUNT];
extern const struct _SCRIPT_ENGINE_TOKEN LalrRhs[RULES_COUNT][MAX_RHS_LEN];
extern const unsigned int LalrRhsSize[RULES_COUNT];
extern const char* LalrNoneTerminalMap[NONETERMINAL_COUNT];
extern const char* LalrTerminalMap[TERMINAL_COUNT];
extern const char* LalrNoneTerminalMap[LALR_NONTERMINAL_COUNT];
extern const char* LalrTerminalMap[LALR_TERMINAL_COUNT];
extern const int LalrGotoTable[LALR_STATE_COUNT][LALR_NONTERMINAL_COUNT];
extern const int LalrActionTable[LALR_STATE_COUNT][LALR_TERMINAL_COUNT];
extern const struct _SCRIPT_ENGINE_TOKEN LalrSemanticRules[RULES_COUNT];

View file

@ -90,6 +90,9 @@ SetGlobalIdentifierVariableType(PSCRIPT_ENGINE_TOKEN Token, VARIABLE_TYPE * Vari
VARIABLE_TYPE *
GetGlobalIdentifierVariableType(PSCRIPT_ENGINE_TOKEN Token);
BOOLEAN
GetGlobalIdentifierIsImplicitType(PSCRIPT_ENGINE_TOKEN Token);
unsigned long long
NewLocalIdentifier(PSCRIPT_ENGINE_TOKEN PTOKEN, unsigned int VariableSize);
@ -102,6 +105,9 @@ SetLocalIdentifierVariableType(PSCRIPT_ENGINE_TOKEN Token, VARIABLE_TYPE * Varia
VARIABLE_TYPE *
GetLocalIdentifierVariableType(PSCRIPT_ENGINE_TOKEN Token);
BOOLEAN
GetLocalIdentifierIsImplicitType(PSCRIPT_ENGINE_TOKEN Token);
int
NewFunctionParameterIdentifier(PSCRIPT_ENGINE_TOKEN Token);

View file

@ -24,6 +24,7 @@ typedef enum _VARIABLE_TYPE_KIND
TY_SHORT,
TY_INT,
TY_LONG,
TY_LLONG,
TY_FLOAT,
TY_DOUBLE,
TY_LDOUBLE,
@ -43,6 +44,17 @@ typedef enum _POINTER_PROVENANCE
POINTER_PROVENANCE_REMOTE,
} POINTER_PROVENANCE;
typedef enum _INTEGER_TYPE_RANK
{
INTEGER_RANK_NONE,
INTEGER_RANK_BOOL,
INTEGER_RANK_CHAR,
INTEGER_RANK_SHORT,
INTEGER_RANK_INT,
INTEGER_RANK_LONG,
INTEGER_RANK_LONG_LONG,
} INTEGER_TYPE_RANK;
typedef struct _STRUCT_MEMBER STRUCT_MEMBER, *PSTRUCT_MEMBER;
typedef struct _VARIABLE_TYPE
@ -57,6 +69,7 @@ typedef struct _VARIABLE_TYPE
char * TagName;
BOOLEAN IsComplete;
PSTRUCT_MEMBER Members;
INTEGER_TYPE_RANK IntegerRank;
} VARIABLE_TYPE, *PVARIABLE_TYPE;
struct _STRUCT_MEMBER
@ -77,11 +90,13 @@ extern VARIABLE_TYPE * VARIABLE_TYPE_CHAR;
extern VARIABLE_TYPE * VARIABLE_TYPE_SHORT;
extern VARIABLE_TYPE * VARIABLE_TYPE_INT;
extern VARIABLE_TYPE * VARIABLE_TYPE_LONG;
extern VARIABLE_TYPE * VARIABLE_TYPE_LLONG;
extern VARIABLE_TYPE * VARIABLE_TYPE_UCHAR;
extern VARIABLE_TYPE * VARIABLE_TYPE_USHORT;
extern VARIABLE_TYPE * VARIABLE_TYPE_UINT;
extern VARIABLE_TYPE * VARIABLE_TYPE_ULONG;
extern VARIABLE_TYPE * VARIABLE_TYPE_ULLONG;
extern VARIABLE_TYPE * VARIABLE_TYPE_FLOAT;
extern VARIABLE_TYPE * VARIABLE_TYPE_DOUBLE;
@ -141,4 +156,19 @@ CreateArrayType(PVARIABLE_TYPE BaseType, unsigned int ArrayLength);
BOOLEAN
AddTypedefType(const char * Name, PVARIABLE_TYPE Type);
PVARIABLE_TYPE
FindTypedefType(const char * Name);
PVARIABLE_TYPE
GetDefaultImplicitVariableType(VOID);
BOOLEAN
IsIntegerVariableType(PVARIABLE_TYPE Type);
PVARIABLE_TYPE
PromoteIntegerVariableType(PVARIABLE_TYPE Type);
PVARIABLE_TYPE
GetCommonVariableType(PVARIABLE_TYPE LeftType, PVARIABLE_TYPE RightType);
#endif

View file

@ -29,6 +29,7 @@
.ThreeOpFunc4->wcsncmp
.OperatorsOneOperand->inc dec reference dereference
.ScriptVariableType->void bool char short int long unsigned signed float double
S->BE
@ -36,13 +37,17 @@ S->BE
BE->B1
B1->B1 || B2 @OR
B1->B1 || LOGICAL_OR_BEGIN B2 @LOGICAL_OR_END
B1->B2
LOGICAL_OR_BEGIN->eps @LOGICAL_OR_BEGIN
B2->B2 && B3 @AND
B2->B2 && LOGICAL_AND_BEGIN B3 @LOGICAL_AND_END
B2->B3
LOGICAL_AND_BEGIN->eps @LOGICAL_AND_BEGIN
B3->B3 | B4 @OR
B3->B4
@ -81,8 +86,10 @@ E10->E12
E10->- E12 @NEG
E10->+ E12
E10->~ E12 @NOT
E10->! E12 @LOGICAL_NOT_TYPED
E10->* E12 @POI
E10->& E12 @REFERENCE
E10->sizeof SIZEOF_VALUE
E12->.ZeroOpFunc2 ( ) @.ZeroOpFunc2
@ -96,8 +103,7 @@ E12->.OneOpFunc4 ( WstringNumber ) @.OneOpFunc4
E12->.TwoOpFunc4 ( WstringNumber , WstringNumber ) @.TwoOpFunc4
E12->.ThreeOpFunc4 ( WstringNumber , WstringNumber , EXP ) @.ThreeOpFunc4
E12->( BE )
E12->( CAST_OR_BOOLEAN
E12->E12 . MEMBER_NAME @MEMBER_DOT_READ
E12->E12 -> MEMBER_NAME @MEMBER_ARROW_READ
@ -121,6 +127,26 @@ E12->_pseudo_register @PUSH
E12->E13 ( VA2 ) @END_OF_CALLING_USER_DEFINED_FUNCTION_WITH_RETURNING_VALUE
CAST_OR_BOOLEAN->CAST_TYPE ) E10 @CAST_SCALAR
CAST_OR_BOOLEAN->STRUCT_CAST_TYPE ) E10 @CAST_SCALAR
CAST_OR_BOOLEAN->BE )
CAST_TYPE->_script_variable_type CAST_TYPE_REST @PUSH
CAST_TYPE_REST->_script_variable_type CAST_TYPE_REST @PUSH
CAST_TYPE_REST->* CAST_POINTERS @DECLARE_POINTER_TYPE
CAST_TYPE_REST->eps
CAST_POINTERS->* CAST_POINTERS @DECLARE_POINTER_TYPE
CAST_POINTERS->eps
STRUCT_CAST_TYPE->struct _local_id CAST_POINTERS @PUSH
SIZEOF_BEGIN->eps @SIZEOF_BEGIN
SIZEOF_VALUE->( SIZEOF_PAREN
SIZEOF_VALUE->SIZEOF_BEGIN E10 @SIZEOF_EXPRESSION
SIZEOF_PAREN->CAST_TYPE ) @SIZEOF_TYPE
SIZEOF_PAREN->STRUCT_CAST_TYPE ) @SIZEOF_TYPE
SIZEOF_PAREN->SIZEOF_BEGIN BE ) @SIZEOF_EXPRESSION
E13->_function_id @PUSH
MEMBER_NAME->_local_id @PUSH

View file

@ -47,7 +47,7 @@
.AssignmentOperator->add_assignment sub_assignment mul_assignment div_assignment mod_assignment asl_assignment asr_assignment and_assignment xor_assignment or_assignment
.SemantiRules->jmp jz jnz mov start_of_do_while start_of_do_while_commands end_of_do_while start_of_for for_inc_dec start_of_for_ommands end_of_if ignore_lvalue push pop call ret struct_forward_declaration struct_definition_begin struct_definition_end struct_variable_declaration struct_member_declaration typedef_declaration struct_pointer struct_array_dimension struct_declarator_complete typed_load typed_store aggregate_copy aggregate_zero struct_initializer_begin struct_initializer_end struct_pointer_cast member_address member_read member_dot_lvalue member_arrow_lvalue member_dot_read member_arrow_read mov_float neg_float add_float sub_float mul_float div_float gt_float lt_float egt_float elt_float equal_float neq_float convert_float
.SemantiRules->jmp jz jnz mov start_of_do_while start_of_do_while_commands end_of_do_while start_of_for for_inc_dec start_of_for_ommands end_of_if ignore_lvalue push pop call ret struct_forward_declaration struct_definition_begin struct_definition_end struct_variable_declaration struct_member_declaration typedef_declaration struct_pointer struct_array_dimension struct_declarator_complete typed_load typed_store aggregate_copy aggregate_zero struct_initializer_begin struct_initializer_end struct_pointer_cast member_address member_read member_dot_lvalue member_arrow_lvalue member_dot_read member_arrow_read mov_float neg_float add_float sub_float mul_float div_float gt_float lt_float egt_float elt_float equal_float neq_float convert_float cast_scalar type_name_begin sizeof_begin sizeof_type sizeof_expression logical_not_typed logical_or_begin logical_or_end logical_and_begin logical_and_end
.Registers->rax eax ax ah al rcx ecx cx ch cl rdx edx dx dh dl rbx ebx bx bh bl rsp esp sp spl rbp ebp bp bpl rsi esi si sil rdi edi di dil r8 r8d r8w r8h r8l r9 r9d r9w r9h r9l r10 r10d r10w r10h r10l r11 r11d r11w r11h r11l r12 r12d r12w r12h r12l r13 r13d r13w r13h r13l r14 r14d r14w r14h r14l r15 r15d r15w r15h r15l ds es fs gs cs ss rflags eflags flags cf pf af zf sf tf if df of iopl nt rf vm ac vif vip id rip eip ip idtr ldtr gdtr tr cr0 cr2 cr3 cr4 cr8 dr0 dr1 dr2 dr3 dr6 dr7
@ -188,9 +188,11 @@ STRUCT_ARRAY_DIMS->[ @PUSH CONST_NUMBER @STRUCT_ARRAY_DIMENSION ] STRUCT_ARRAY_D
STRUCT_ARRAY_DIMS->eps
# Typedef declarations are accepted, but typedef-name lookup is implemented in
# a later type-system stage. Until then an alias cannot be used as a type.
TYPEDEF_DECLARATION->typedef TYPEDEF_BASE_TYPE STRUCT_POINTERS @PUSH _local_id ; @TYPEDEF_DECLARATION
# Register the alias before consuming ';'. The LL(1) driver scans one token of
# lookahead after every terminal, so placing the semantic action after ';'
# would classify the first token in the next declaration before the typedef
# exists in the type context.
TYPEDEF_DECLARATION->typedef TYPEDEF_BASE_TYPE STRUCT_POINTERS @PUSH _local_id @TYPEDEF_DECLARATION ;
TYPEDEF_BASE_TYPE->STRUCT_SCALAR_TYPE
TYPEDEF_BASE_TYPE->struct @PUSH _local_id
@ -337,7 +339,34 @@ E12->.OneOpFunc4 ( WstringNumber @.OneOpFunc4 )
E12->.TwoOpFunc4 ( WstringNumber , WstringNumber @.TwoOpFunc4 )
E12->.ThreeOpFunc4 ( WstringNumber , WstringNumber , EXPRESSION @.ThreeOpFunc4 )
E12->( EXPRESSION )
E12->( PAREN_EXPRESSION
PAREN_EXPRESSION->@TYPE_NAME_BEGIN VARIABLE_TYPE1 CAST_TYPE_REST ) E12 @CAST_SCALAR
PAREN_EXPRESSION->@TYPE_NAME_BEGIN struct @PUSH _local_id CAST_POINTERS ) E12 @CAST_SCALAR
PAREN_EXPRESSION->EXPRESSION )
CAST_TYPE_REST->VARIABLE_TYPE1 CAST_TYPE_REST
CAST_TYPE_REST->* @DECLARE_POINTER_TYPE CAST_POINTERS
CAST_TYPE_REST->eps
CAST_POINTERS->* @DECLARE_POINTER_TYPE CAST_POINTERS
CAST_POINTERS->eps
E12->sizeof SIZEOF_OPERAND
SIZEOF_OPERAND->( SIZEOF_PAREN
SIZEOF_OPERAND->@SIZEOF_BEGIN SIZEOF_UNPAREN @SIZEOF_EXPRESSION
SIZEOF_PAREN->@TYPE_NAME_BEGIN VARIABLE_TYPE1 CAST_TYPE_REST ) @SIZEOF_TYPE
SIZEOF_PAREN->@TYPE_NAME_BEGIN struct @PUSH _local_id CAST_POINTERS ) @SIZEOF_TYPE
SIZEOF_PAREN->@SIZEOF_BEGIN EXPRESSION ) @SIZEOF_EXPRESSION
SIZEOF_UNPAREN->L_VALUE MEMBER_READ_SUFFIX ARRAY_DIMS_READ_OPT
SIZEOF_UNPAREN->CONST_NUMBER
SIZEOF_UNPAREN->@PUSH _pseudo_register
SIZEOF_UNPAREN->- E12 @NEG
SIZEOF_UNPAREN->+ E12
SIZEOF_UNPAREN->~ E12 @NOT
SIZEOF_UNPAREN->! E12 @LOGICAL_NOT_TYPED
SIZEOF_UNPAREN->* E12 @POI
SIZEOF_UNPAREN->& E12 @REFERENCE
E12->L_VALUE MEMBER_READ_SUFFIX ARRAY_DIMS_READ_OPT
@ -372,6 +401,7 @@ E12->@PUSH _pseudo_register
E12->- E12 @NEG
E12->+ E12
E12->~ E12 @NOT
E12->! E12 @LOGICAL_NOT_TYPED
E12->* E12 @POI
E12->& E12 @REFERENCE

View file

@ -14,9 +14,23 @@
"""
import os
import subprocess
import sys
from ll1_parser import *
from lalr1_parser import *
def EnsureDeterministicHashSeed():
"""Restart the generator with stable set/dict iteration ordering."""
if os.environ.get("PYTHONHASHSEED") == "0":
return
Environment = os.environ.copy()
Environment["PYTHONHASHSEED"] = "0"
raise SystemExit(subprocess.call([sys.executable] + sys.argv, env=Environment))
class Generator():
def __init__(self):
self.SourceFile = open("..\\code\\parse-table.c", "w")
@ -91,6 +105,20 @@ object ScriptConstants {
val SYMBOL_VALUE_KIND_INTEGER = 0
val SYMBOL_VALUE_KIND_FLOAT32 = 1
val SYMBOL_VALUE_KIND_FLOAT64 = 2
val SCRIPT_SCALAR_TYPE_INVALID = 0
val SCRIPT_SCALAR_TYPE_BOOL = 1
val SCRIPT_SCALAR_TYPE_I8 = 2
val SCRIPT_SCALAR_TYPE_I16 = 3
val SCRIPT_SCALAR_TYPE_I32 = 4
val SCRIPT_SCALAR_TYPE_I64 = 5
val SCRIPT_SCALAR_TYPE_U8 = 6
val SCRIPT_SCALAR_TYPE_U16 = 7
val SCRIPT_SCALAR_TYPE_U32 = 8
val SCRIPT_SCALAR_TYPE_U64 = 9
val SCRIPT_SCALAR_TYPE_F32 = 10
val SCRIPT_SCALAR_TYPE_F64 = 11
val SCRIPT_SCALAR_TYPE_POINTER = 12
val SCRIPT_SCALAR_TYPE_F80 = 13
}
/**
@ -180,6 +208,21 @@ typedef struct ACTION_BUFFER {
#define SCRIPT_ENGINE_ADDRESS_SPACE_LOCAL 1
#define SCRIPT_ENGINE_ADDRESS_SPACE_REMOTE 2
#define SCRIPT_SCALAR_TYPE_INVALID 0
#define SCRIPT_SCALAR_TYPE_BOOL 1
#define SCRIPT_SCALAR_TYPE_I8 2
#define SCRIPT_SCALAR_TYPE_I16 3
#define SCRIPT_SCALAR_TYPE_I32 4
#define SCRIPT_SCALAR_TYPE_I64 5
#define SCRIPT_SCALAR_TYPE_U8 6
#define SCRIPT_SCALAR_TYPE_U16 7
#define SCRIPT_SCALAR_TYPE_U32 8
#define SCRIPT_SCALAR_TYPE_U64 9
#define SCRIPT_SCALAR_TYPE_F32 10
#define SCRIPT_SCALAR_TYPE_F64 11
#define SCRIPT_SCALAR_TYPE_POINTER 12
#define SCRIPT_SCALAR_TYPE_F80 13
static const char *const SymbolTypeNames[] = {
"SYMBOL_UNDEFINED",
"SYMBOL_GLOBAL_ID_TYPE",
@ -219,7 +262,8 @@ static const char *const SymbolTypeNames[] = {
if __name__ == "__main__":
EnsureDeterministicHashSeed()
gen = Generator()
gen.Run()

View file

@ -142,8 +142,8 @@ class LALR1Parser:
self.SourceFile.write("};\n")
def WriteTerminalList(self):
self.SourceFile.write("const char* LalrTerminalMap[TERMINAL_COUNT]= \n{\n")
self.HeaderFile.write("extern const char* LalrTerminalMap[TERMINAL_COUNT];\n")
self.SourceFile.write("const char* LalrTerminalMap[LALR_TERMINAL_COUNT]=\n{\n")
self.HeaderFile.write("extern const char* LalrTerminalMap[LALR_TERMINAL_COUNT];\n")
Counter = 0
for X in self.TerminalList:
if Counter == len(self.TerminalList)-1:
@ -154,8 +154,8 @@ class LALR1Parser:
self.SourceFile.write("};\n")
def WriteNoneTermianlList(self):
self.SourceFile.write("const char* LalrNoneTerminalMap[NONETERMINAL_COUNT]= \n{\n")
self.HeaderFile.write("extern const char* LalrNoneTerminalMap[NONETERMINAL_COUNT];\n")
self.SourceFile.write("const char* LalrNoneTerminalMap[LALR_NONTERMINAL_COUNT]=\n{\n")
self.HeaderFile.write("extern const char* LalrNoneTerminalMap[LALR_NONTERMINAL_COUNT];\n")
Counter = 0
for X in self.NonTerminalList:
if Counter == len(self.NonTerminalList)-1:
@ -292,9 +292,9 @@ class LALR1Parser:
self.TerminalSet.add("$")
self.NonTerminalList = list(self.NonTerminalSet)
self.NonTerminalList = sorted(self.NonTerminalSet)
self.TerminalList = list(self.TerminalSet)
self.TerminalList = sorted(self.TerminalSet)
def FillActionTable(self):
self.ActionTable = [[self.INVALID for y in range(len(self.TerminalList))] for X in range(self.StateCount)]
@ -305,9 +305,21 @@ class LALR1Parser:
Action = self.ParseTable.action[RowId][Terminal]
Type = None
StateId = None
for Element in Action:
Type = Element[0]
StateId = Element[1]
Elements = list(Action)
ShiftActions = [Element for Element in Elements if Element[0] == 'S']
AcceptActions = [Element for Element in Elements if Element[0] == 'accept']
ReduceActions = [Element for Element in Elements if Element[0] == 'R']
if AcceptActions:
Type, StateId = AcceptActions[0]
elif ShiftActions:
# Match conventional yacc behavior for shift/reduce
# conflicts. In particular, sizeof '(' must shift so
# SIZEOF_PAREN can distinguish a type-name from an
# expression instead of prematurely reducing the
# unparenthesized sizeof production.
Type, StateId = sorted(ShiftActions, key=lambda Element: int(Element[1]))[0]
elif ReduceActions:
Type, StateId = sorted(ReduceActions, key=lambda Element: int(Element[1]))[0]
if Type != None:
if Type == 'S':
self.ActionTable[RowId][self.GetTerminalId(Terminal)] = StateId

View file

@ -48,7 +48,7 @@ class LL1Parser:
self.MAXIMUM_RHS_LEN = 0
self.SPECIAL_TOKENS = ['%', '+', '~', '++', '-', '--', '->', '.', "*", "/", "=", "==", "!=", ",", ";", "(", ")", "{", "}", "|", "||", ">>", ">=", "<<", "<=", "&", "&&", "^",
self.SPECIAL_TOKENS = ['%', '+', '~', '!', '++', '-', '--', '->', '.', "*", "/", "=", "==", "!=", ",", ";", "(", ")", "{", "}", "|", "||", ">>", ">=", "<<", "<=", "&", "&&", "^",
"+=", "-=", "*=", "/=", "%=", "<<=", ">>=", "&=", "^=", "|=" , "[", "]"]
# INVALID rule indicator
@ -430,9 +430,9 @@ class LL1Parser:
self.TerminalSet.add("$")
self.NonTerminalList = list(self.NonTerminalSet)
self.NonTerminalList = sorted(self.NonTerminalSet)
self.TerminalList = list(self.TerminalSet)
self.TerminalList = sorted(self.TerminalSet)
def WriteSemanticMaps(self):
@ -453,11 +453,23 @@ class LL1Parser:
"convert_float"
}
aggregate_keywords = {"struct", "typedef"}
legacy_semantics = [x for x in self.SemantiRulesList if x not in aggregate_semantics]
append_only_semantics = [
"cast_scalar",
"add_typed", "sub_typed", "mul_typed", "div_typed", "mod_typed",
"bitwise_and_typed", "bitwise_or_typed", "bitwise_xor_typed",
"shift_left_typed", "shift_right_typed",
"gt_typed", "lt_typed", "egt_typed", "elt_typed", "equal_typed", "neq_typed",
"neg_typed", "bitwise_not_typed", "logical_not_typed", "pointer_diff"
]
compiler_only_semantics = {
"type_name_begin", "sizeof_begin", "sizeof_type", "sizeof_expression",
"logical_or_begin", "logical_or_end", "logical_and_begin", "logical_and_end"
}
legacy_semantics = [x for x in self.SemantiRulesList if x not in aggregate_semantics and x not in append_only_semantics and x not in compiler_only_semantics]
new_semantics = [x for x in self.SemantiRulesList if x in aggregate_semantics]
legacy_keywords = [x for x in self.keywordList if x not in aggregate_keywords]
new_keywords = [x for x in self.keywordList if x in aggregate_keywords]
numbered_semantics = legacy_semantics + legacy_keywords + new_semantics + new_keywords
numbered_semantics = legacy_semantics + legacy_keywords + new_semantics + new_keywords + append_only_semantics
self.CommonHeaderFileScala.write("object ScriptEvalFunc {\n object ScriptOperators extends ChiselEnum {\n val ")
@ -506,7 +518,10 @@ class LL1Parser:
self.SourceFile.write("{\"@" + X.upper() + "\", "+ "FUNC_" + X.upper() + "},\n")
for X in self.SemantiRulesList:
self.SourceFile.write("{\"@" + X.upper() + "\", "+ "FUNC_" + X.upper() + "},\n")
if X in compiler_only_semantics:
self.SourceFile.write("{\"@" + X.upper() + "\", FUNC_UNDEFINED},\n")
else:
self.SourceFile.write("{\"@" + X.upper() + "\", "+ "FUNC_" + X.upper() + "},\n")
for X in self.keywordList:
self.SourceFile.write("{\"@" + X.upper() + "\", "+ "FUNC_" + X.upper() + "},\n")
@ -872,8 +887,9 @@ class LL1Parser:
self.ParseTable[i][j] = RuleId
else:
print("Error! Input grammar is not LL1.")
print("Error! Input grammar is not LL1: " + Lhs +
" on " + Terminal + " conflicts between rules " +
str(self.ParseTable[i][j]) + " and " + str(RuleId) + ".")
exit()
j += 1

View file

@ -114,6 +114,16 @@ typedef struct _SCRIPT_ENGINE_SOFT_FLOAT
SCRIPT_ENGINE_UINT128 Significand;
} SCRIPT_ENGINE_SOFT_FLOAT;
static BOOLEAN
ScriptEngineSoftFloatUnpack(UINT64 ValueKind, UINT64 RawBits, SCRIPT_ENGINE_SOFT_FLOAT * Value);
static BOOLEAN
ScriptEngineSoftFloatPack(UINT64 ValueKind,
BOOLEAN Negative,
INT32 Exponent,
const SCRIPT_ENGINE_UINT128 * InputSignificand,
PUINT64 RawBits);
static BOOLEAN
ScriptEngineIntegerSymbolIsWritable(PSCRIPT_ENGINE_GENERAL_REGISTERS Registers, PSYMBOL Symbol)
{
@ -123,6 +133,259 @@ ScriptEngineIntegerSymbolIsWritable(PSCRIPT_ENGINE_GENERAL_REGISTERS Registers,
Symbol->Value < MAX_STACK_BUFFER_COUNT - Registers->StackBaseIndx;
}
static BOOLEAN
ScriptEngineHasOperands(PSYMBOL_BUFFER CodeBuffer, UINT64 Index, UINT32 Count)
{
return Index <= CodeBuffer->Pointer && Count <= CodeBuffer->Pointer - Index;
}
static BOOLEAN
ScriptEngineScalarTypeIsInteger(UINT64 TypeId)
{
return TypeId >= SCRIPT_SCALAR_TYPE_BOOL && TypeId <= SCRIPT_SCALAR_TYPE_U64;
}
static BOOLEAN
ScriptEngineScalarTypeIsFloating(UINT64 TypeId)
{
return TypeId == SCRIPT_SCALAR_TYPE_F32 || TypeId == SCRIPT_SCALAR_TYPE_F64;
}
static UINT32
ScriptEngineScalarTypeWidth(UINT64 TypeId)
{
switch (TypeId)
{
case SCRIPT_SCALAR_TYPE_BOOL:
case SCRIPT_SCALAR_TYPE_I8:
case SCRIPT_SCALAR_TYPE_U8:
return 8;
case SCRIPT_SCALAR_TYPE_I16:
case SCRIPT_SCALAR_TYPE_U16:
return 16;
case SCRIPT_SCALAR_TYPE_I32:
case SCRIPT_SCALAR_TYPE_U32:
case SCRIPT_SCALAR_TYPE_F32:
return 32;
case SCRIPT_SCALAR_TYPE_I64:
case SCRIPT_SCALAR_TYPE_U64:
case SCRIPT_SCALAR_TYPE_F64:
case SCRIPT_SCALAR_TYPE_POINTER:
return 64;
default:
return 0;
}
}
static BOOLEAN
ScriptEngineScalarTypeIsSigned(UINT64 TypeId)
{
return TypeId == SCRIPT_SCALAR_TYPE_I8 || TypeId == SCRIPT_SCALAR_TYPE_I16 ||
TypeId == SCRIPT_SCALAR_TYPE_I32 || TypeId == SCRIPT_SCALAR_TYPE_I64;
}
static UINT64
ScriptEngineNormalizeInteger(UINT64 Value, UINT64 TypeId)
{
UINT32 Width = ScriptEngineScalarTypeWidth(TypeId);
UINT64 Mask;
if (TypeId == SCRIPT_SCALAR_TYPE_BOOL)
return Value != 0;
if (Width == 64)
return Value;
Mask = (1ULL << Width) - 1;
Value &= Mask;
if (ScriptEngineScalarTypeIsSigned(TypeId) && (Value & (1ULL << (Width - 1))))
Value |= ~Mask;
return Value;
}
static BOOLEAN
ScriptEngineIntegerToFloat(UINT64 Value, UINT64 SourceType, UINT64 DestinationType, PUINT64 Result)
{
SCRIPT_ENGINE_UINT128 Significand = {0, 0};
BOOLEAN Negative = FALSE;
UINT64 Magnitude;
INT32 Exponent = 0;
Value = ScriptEngineNormalizeInteger(Value, SourceType);
if (ScriptEngineScalarTypeIsSigned(SourceType) && (Value & 0x8000000000000000ULL))
{
Negative = TRUE;
Magnitude = 0ULL - Value;
}
else
{
Magnitude = Value;
}
if (Magnitude)
{
UINT64 Scan = Magnitude;
while (Scan >>= 1) Exponent++;
Significand.High = Magnitude << (63 - Exponent);
}
return ScriptEngineSoftFloatPack(DestinationType == SCRIPT_SCALAR_TYPE_F32 ?
SYMBOL_VALUE_KIND_FLOAT32 : SYMBOL_VALUE_KIND_FLOAT64,
Negative,
Exponent,
&Significand,
Result);
}
static BOOLEAN
ScriptEngineFloatToInteger(UINT64 Value, UINT64 SourceType, UINT64 DestinationType, PUINT64 Result)
{
SCRIPT_ENGINE_SOFT_FLOAT FloatValue;
UINT64 Magnitude;
UINT64 Maximum;
UINT32 Width = ScriptEngineScalarTypeWidth(DestinationType);
if (!ScriptEngineSoftFloatUnpack(SourceType == SCRIPT_SCALAR_TYPE_F32 ?
SYMBOL_VALUE_KIND_FLOAT32 : SYMBOL_VALUE_KIND_FLOAT64,
Value,
&FloatValue))
return FALSE;
if (FloatValue.IsZero || FloatValue.Exponent < 0)
{
*Result = 0;
return TRUE;
}
if (FloatValue.Exponent > 63)
return FALSE;
Magnitude = FloatValue.Significand.High >> (63 - FloatValue.Exponent);
if (ScriptEngineScalarTypeIsSigned(DestinationType))
{
Maximum = Width == 64 ? 0x7fffffffffffffffULL : (1ULL << (Width - 1)) - 1;
if ((!FloatValue.Negative && Magnitude > Maximum) ||
(FloatValue.Negative && Magnitude > Maximum + 1))
return FALSE;
*Result = FloatValue.Negative ? 0ULL - Magnitude : Magnitude;
}
else
{
Maximum = Width == 64 ? ~0ULL : (1ULL << Width) - 1;
if (FloatValue.Negative || Magnitude > Maximum)
return FALSE;
*Result = Magnitude;
}
*Result = ScriptEngineNormalizeInteger(*Result, DestinationType);
return TRUE;
}
static BOOLEAN
ScriptEngineCastScalar(UINT64 Value, UINT64 SourceType, UINT64 DestinationType, PUINT64 Result)
{
if (SourceType == SCRIPT_SCALAR_TYPE_F80 || DestinationType == SCRIPT_SCALAR_TYPE_F80 ||
SourceType == SCRIPT_SCALAR_TYPE_INVALID || DestinationType == SCRIPT_SCALAR_TYPE_INVALID)
return FALSE;
if ((ScriptEngineScalarTypeIsInteger(SourceType) || SourceType == SCRIPT_SCALAR_TYPE_POINTER) &&
(ScriptEngineScalarTypeIsInteger(DestinationType) || DestinationType == SCRIPT_SCALAR_TYPE_POINTER))
{
*Result = DestinationType == SCRIPT_SCALAR_TYPE_POINTER ?
Value : ScriptEngineNormalizeInteger(Value, DestinationType);
return TRUE;
}
if (ScriptEngineScalarTypeIsFloating(SourceType) && ScriptEngineScalarTypeIsFloating(DestinationType))
{
SCRIPT_ENGINE_SOFT_FLOAT Converted;
if (!ScriptEngineSoftFloatUnpack(SourceType == SCRIPT_SCALAR_TYPE_F32 ?
SYMBOL_VALUE_KIND_FLOAT32 : SYMBOL_VALUE_KIND_FLOAT64,
Value,
&Converted))
return FALSE;
return ScriptEngineSoftFloatPack(DestinationType == SCRIPT_SCALAR_TYPE_F32 ?
SYMBOL_VALUE_KIND_FLOAT32 : SYMBOL_VALUE_KIND_FLOAT64,
Converted.Negative,
Converted.Exponent,
&Converted.Significand,
Result);
}
if (ScriptEngineScalarTypeIsInteger(SourceType) && ScriptEngineScalarTypeIsFloating(DestinationType))
return ScriptEngineIntegerToFloat(Value, SourceType, DestinationType, Result);
if (ScriptEngineScalarTypeIsFloating(SourceType) && ScriptEngineScalarTypeIsInteger(DestinationType))
return ScriptEngineFloatToInteger(Value, SourceType, DestinationType, Result);
return FALSE;
}
static BOOLEAN
ScriptEngineExecuteTypedBinary(UINT64 Opcode,
UINT64 Right,
UINT64 Left,
UINT64 TypeId,
PUINT64 Result)
{
UINT32 Width;
UINT64 SignedMinimum;
if (TypeId == SCRIPT_SCALAR_TYPE_POINTER)
{
if (Opcode == FUNC_GT_TYPED) *Result = Left > Right;
else if (Opcode == FUNC_LT_TYPED) *Result = Left < Right;
else if (Opcode == FUNC_EGT_TYPED) *Result = Left >= Right;
else if (Opcode == FUNC_ELT_TYPED) *Result = Left <= Right;
else if (Opcode == FUNC_EQUAL_TYPED) *Result = Left == Right;
else if (Opcode == FUNC_NEQ_TYPED) *Result = Left != Right;
else return FALSE;
return TRUE;
}
if (!ScriptEngineScalarTypeIsInteger(TypeId))
return FALSE;
Width = ScriptEngineScalarTypeWidth(TypeId);
Left = ScriptEngineNormalizeInteger(Left, TypeId);
Right = ScriptEngineNormalizeInteger(Right, TypeId);
switch (Opcode)
{
case FUNC_ADD_TYPED: *Result = Left + Right; break;
case FUNC_SUB_TYPED: *Result = Left - Right; break;
case FUNC_MUL_TYPED: *Result = Left * Right; break;
case FUNC_DIV_TYPED:
case FUNC_MOD_TYPED:
if (!Right) return FALSE;
if (ScriptEngineScalarTypeIsSigned(TypeId))
{
SignedMinimum = Width == 64 ? 0x8000000000000000ULL : (1ULL << (Width - 1));
SignedMinimum = ScriptEngineNormalizeInteger(SignedMinimum, TypeId);
if (Left == SignedMinimum && Right == ~0ULL) return FALSE;
*Result = Opcode == FUNC_DIV_TYPED ?
(UINT64)((INT64)Left / (INT64)Right) :
(UINT64)((INT64)Left % (INT64)Right);
}
else
{
*Result = Opcode == FUNC_DIV_TYPED ? Left / Right : Left % Right;
}
break;
case FUNC_BITWISE_AND_TYPED: *Result = Left & Right; break;
case FUNC_BITWISE_OR_TYPED: *Result = Left | Right; break;
case FUNC_BITWISE_XOR_TYPED: *Result = Left ^ Right; break;
case FUNC_SHIFT_LEFT_TYPED:
if (Right >= Width) return FALSE;
*Result = Left << Right;
break;
case FUNC_SHIFT_RIGHT_TYPED:
if (Right >= Width) return FALSE;
*Result = ScriptEngineScalarTypeIsSigned(TypeId) ?
(UINT64)((INT64)Left >> Right) : Left >> Right;
break;
case FUNC_GT_TYPED: *Result = ScriptEngineScalarTypeIsSigned(TypeId) ? (INT64)Left > (INT64)Right : Left > Right; return TRUE;
case FUNC_LT_TYPED: *Result = ScriptEngineScalarTypeIsSigned(TypeId) ? (INT64)Left < (INT64)Right : Left < Right; return TRUE;
case FUNC_EGT_TYPED: *Result = ScriptEngineScalarTypeIsSigned(TypeId) ? (INT64)Left >= (INT64)Right : Left >= Right; return TRUE;
case FUNC_ELT_TYPED: *Result = ScriptEngineScalarTypeIsSigned(TypeId) ? (INT64)Left <= (INT64)Right : Left <= Right; return TRUE;
case FUNC_EQUAL_TYPED: *Result = Left == Right; return TRUE;
case FUNC_NEQ_TYPED: *Result = Left != Right; return TRUE;
default: return FALSE;
}
*Result = ScriptEngineNormalizeInteger(*Result, TypeId);
return TRUE;
}
static BOOLEAN
ScriptEngineIsFloatingComparisonOpcode(UINT64 Opcode)
{
@ -901,6 +1164,11 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs,
{
case FUNC_TYPED_LOAD:
{
if (!ScriptEngineHasOperands(CodeBuffer, *Indx, 4))
{
HasError = TRUE;
break;
}
Src0 = CodeBuffer->Head + (*Indx)++;
Src1 = CodeBuffer->Head + (*Indx)++;
Src2 = CodeBuffer->Head + (*Indx)++;
@ -919,6 +1187,11 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs,
case FUNC_TYPED_STORE:
{
if (!ScriptEngineHasOperands(CodeBuffer, *Indx, 4))
{
HasError = TRUE;
break;
}
Src0 = CodeBuffer->Head + (*Indx)++;
Src1 = CodeBuffer->Head + (*Indx)++;
Src2 = CodeBuffer->Head + (*Indx)++;
@ -937,6 +1210,11 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs,
{
BYTE ZeroBuffer[64] = {0};
UINT64 Done = 0;
if (!ScriptEngineHasOperands(CodeBuffer, *Indx, 3))
{
HasError = TRUE;
break;
}
Src0 = CodeBuffer->Head + (*Indx)++;
Src1 = CodeBuffer->Head + (*Indx)++;
Src2 = CodeBuffer->Head + (*Indx)++;
@ -958,6 +1236,11 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs,
BYTE MovingBuffer[64];
UINT64 Done = 0;
BOOLEAN Backward;
if (!ScriptEngineHasOperands(CodeBuffer, *Indx, 5))
{
HasError = TRUE;
break;
}
Src0 = CodeBuffer->Head + (*Indx)++;
Src1 = CodeBuffer->Head + (*Indx)++;
Src2 = CodeBuffer->Head + (*Indx)++;
@ -1282,6 +1565,12 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs,
case FUNC_MEMCPY:
if (!ScriptEngineHasOperands(CodeBuffer, *Indx, 3))
{
HasError = TRUE;
break;
}
Src0 = (PSYMBOL)((unsigned long long)CodeBuffer->Head +
(unsigned long long)(*Indx * sizeof(SYMBOL)));
@ -1305,7 +1594,21 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs,
SrcVal2 =
GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src2, FALSE);
ScriptEngineFunctionMemcpy(SrcVal2, SrcVal1, (UINT32)SrcVal0, &HasError);
if (SrcVal0 == 0 || SrcVal0 > 0xffffffffULL)
{
HasError = TRUE;
break;
}
if (ScriptEngineTypedLocalRangeIsValid(ScriptGeneralRegisters, SrcVal2, (UINT32)SrcVal0) &&
ScriptEngineTypedLocalRangeIsValid(ScriptGeneralRegisters, SrcVal1, (UINT32)SrcVal0))
{
memmove((PVOID)SrcVal2, (PVOID)SrcVal1, (SIZE_T)SrcVal0);
}
else
{
ScriptEngineFunctionMemcpy(SrcVal2, SrcVal1, (UINT32)SrcVal0, &HasError);
}
break;
@ -2569,6 +2872,173 @@ ScriptEngineExecute(PGUEST_REGS GuestRegs,
break;
}
case FUNC_CAST_SCALAR:
{
UINT64 SourceType;
UINT64 DestinationType;
if (!ScriptEngineHasOperands(CodeBuffer, *Indx, 4))
{
HasError = TRUE;
break;
}
Src0 = CodeBuffer->Head + (*Indx)++;
Des = CodeBuffer->Head + (*Indx)++;
Src1 = CodeBuffer->Head + (*Indx)++;
Src2 = CodeBuffer->Head + (*Indx)++;
SourceType = GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE);
DestinationType = GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src2, FALSE);
if ((ScriptEngineScalarTypeIsFloating(SourceType) ?
!ScriptEngineFloatingSymbolIsReadable(ScriptGeneralRegisters, Src0) :
Src0->Len != SYMBOL_VALUE_KIND_INTEGER) ||
(ScriptEngineScalarTypeIsFloating(DestinationType) ?
!ScriptEngineFloatingSymbolIsWritable(ScriptGeneralRegisters, Des) :
!ScriptEngineIntegerSymbolIsWritable(ScriptGeneralRegisters, Des)))
{
HasError = TRUE;
break;
}
SrcVal0 = GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE);
if (!ScriptEngineCastScalar(SrcVal0, SourceType, DestinationType, &DesVal))
{
HasError = TRUE;
break;
}
SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal);
break;
}
case FUNC_ADD_TYPED:
case FUNC_SUB_TYPED:
case FUNC_MUL_TYPED:
case FUNC_DIV_TYPED:
case FUNC_MOD_TYPED:
case FUNC_BITWISE_AND_TYPED:
case FUNC_BITWISE_OR_TYPED:
case FUNC_BITWISE_XOR_TYPED:
case FUNC_SHIFT_LEFT_TYPED:
case FUNC_SHIFT_RIGHT_TYPED:
case FUNC_GT_TYPED:
case FUNC_LT_TYPED:
case FUNC_EGT_TYPED:
case FUNC_ELT_TYPED:
case FUNC_EQUAL_TYPED:
case FUNC_NEQ_TYPED:
{
UINT64 OperationType;
if (!ScriptEngineHasOperands(CodeBuffer, *Indx, 4))
{
HasError = TRUE;
break;
}
Src0 = CodeBuffer->Head + (*Indx)++;
Src1 = CodeBuffer->Head + (*Indx)++;
Des = CodeBuffer->Head + (*Indx)++;
Src2 = CodeBuffer->Head + (*Indx)++;
OperationType = GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src2, FALSE);
if (Src0->Len != SYMBOL_VALUE_KIND_INTEGER || Src1->Len != SYMBOL_VALUE_KIND_INTEGER ||
!ScriptEngineIntegerSymbolIsWritable(ScriptGeneralRegisters, Des))
{
HasError = TRUE;
break;
}
SrcVal0 = GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE);
SrcVal1 = GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE);
if (!ScriptEngineExecuteTypedBinary(Operator->Value, SrcVal0, SrcVal1, OperationType, &DesVal))
{
HasError = TRUE;
break;
}
SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal);
break;
}
case FUNC_NEG_TYPED:
case FUNC_BITWISE_NOT_TYPED:
case FUNC_LOGICAL_NOT_TYPED:
{
UINT64 OperationType;
if (!ScriptEngineHasOperands(CodeBuffer, *Indx, 3))
{
HasError = TRUE;
break;
}
Src0 = CodeBuffer->Head + (*Indx)++;
Des = CodeBuffer->Head + (*Indx)++;
Src1 = CodeBuffer->Head + (*Indx)++;
OperationType = GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE);
if ((!ScriptEngineScalarTypeIsInteger(OperationType) && OperationType != SCRIPT_SCALAR_TYPE_POINTER &&
!(Operator->Value == FUNC_LOGICAL_NOT_TYPED && ScriptEngineScalarTypeIsFloating(OperationType))) ||
(ScriptEngineScalarTypeIsFloating(OperationType) ?
!ScriptEngineFloatingSymbolIsReadable(ScriptGeneralRegisters, Src0) :
Src0->Len != SYMBOL_VALUE_KIND_INTEGER) ||
!ScriptEngineIntegerSymbolIsWritable(ScriptGeneralRegisters, Des))
{
HasError = TRUE;
break;
}
SrcVal0 = GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE);
if (Operator->Value == FUNC_LOGICAL_NOT_TYPED)
{
if (OperationType == SCRIPT_SCALAR_TYPE_F32)
DesVal = (SrcVal0 & 0x7fffffffULL) == 0;
else if (OperationType == SCRIPT_SCALAR_TYPE_F64)
DesVal = (SrcVal0 & 0x7fffffffffffffffULL) == 0;
else
DesVal = SrcVal0 == 0;
}
else if (Operator->Value == FUNC_NEG_TYPED)
DesVal = ScriptEngineNormalizeInteger(0ULL - SrcVal0, OperationType);
else
DesVal = ScriptEngineNormalizeInteger(~SrcVal0, OperationType);
SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal);
break;
}
case FUNC_POINTER_DIFF:
{
UINT64 ElementSize;
UINT64 Magnitude;
BOOLEAN Negative;
if (!ScriptEngineHasOperands(CodeBuffer, *Indx, 4))
{
HasError = TRUE;
break;
}
Src0 = CodeBuffer->Head + (*Indx)++;
Src1 = CodeBuffer->Head + (*Indx)++;
Des = CodeBuffer->Head + (*Indx)++;
Src2 = CodeBuffer->Head + (*Indx)++;
ElementSize = GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src2, FALSE);
if (!ElementSize || Src0->Len != SYMBOL_VALUE_KIND_INTEGER ||
Src1->Len != SYMBOL_VALUE_KIND_INTEGER ||
!ScriptEngineIntegerSymbolIsWritable(ScriptGeneralRegisters, Des))
{
HasError = TRUE;
break;
}
SrcVal0 = GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src0, FALSE);
SrcVal1 = GetValue(GuestRegs, ActionDetail, ScriptGeneralRegisters, Src1, FALSE);
Negative = SrcVal1 < SrcVal0;
Magnitude = Negative ? SrcVal0 - SrcVal1 : SrcVal1 - SrcVal0;
if (Magnitude % ElementSize)
{
HasError = TRUE;
break;
}
Magnitude /= ElementSize;
if ((!Negative && Magnitude > 0x7fffffffffffffffULL) ||
(Negative && Magnitude > 0x8000000000000000ULL))
{
HasError = TRUE;
break;
}
DesVal = Negative ? 0ULL - Magnitude : Magnitude;
SetValue(GuestRegs, ScriptGeneralRegisters, Des, DesVal);
break;
}
case FUNC_NEG_FLOAT:
if (*Indx > CodeBuffer->Pointer || CodeBuffer->Pointer - *Indx < 2)
{

@ -1 +1 @@
Subproject commit a8f8b9231e04a47fa5426b89641db810ca90a88d
Subproject commit 3fbd59540fd90cda22ad1d00c18129539202070b