mirror of
https://github.com/HyperDbg/HyperDbg
synced 2026-08-15 06:29:09 -04:00
update variable type and add float type in script enginr
This commit is contained in:
parent
ec5fe7cc8a
commit
d44c726dff
25 changed files with 3595 additions and 1301 deletions
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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");
|
||||
|
|
|
|||
163
hyperdbg/hyperdbg-test/code/tests/test-script-variable-types.cpp
Normal file
163
hyperdbg/hyperdbg-test/code/tests/test-script-variable-types.cpp
Normal 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; }");
|
||||
}
|
||||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -30,4 +30,5 @@ TestSemanticScripts();
|
|||
BOOLEAN
|
||||
TestScriptEngineFloatingPoint();
|
||||
|
||||
#define TEST_CASE_PARAMETER_FOR_SCRIPT_FLOATING_POINT "test-script-floating-point"
|
||||
BOOLEAN
|
||||
TestScriptEngineVariableTypes();
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
Loading…
Add table
Add a link
Reference in a new issue