mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-14 09:18:09 +00:00
1581 lines
69 KiB
C
1581 lines
69 KiB
C
// Copyright (c) Epic Games Tools
|
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
|
|
|
internal DW_PieceNode *
|
|
dw_piece_list_push(Arena *arena, DW_PieceList *list, DW_Piece v)
|
|
{
|
|
DW_PieceNode *n = push_array(arena, DW_PieceNode, 1);
|
|
n->v = v;
|
|
SLLQueuePush(list->first, list->last, n);
|
|
list->count += 1;
|
|
return n;
|
|
}
|
|
|
|
internal DW_ExprValueType
|
|
dw_expr_unsigned_value_type_from_bit_size(U64 bit_size)
|
|
{
|
|
switch (bit_size) {
|
|
case 8: return DW_ExprValueType_U8;
|
|
case 16: return DW_ExprValueType_U16;
|
|
case 32: return DW_ExprValueType_U32;
|
|
case 64: return DW_ExprValueType_U64;
|
|
case 128: return DW_ExprValueType_U128;
|
|
case 256: return DW_ExprValueType_U256;
|
|
case 512: return DW_ExprValueType_U512;
|
|
}
|
|
AssertAlways(0 && "no suitable unsigned type was found for the specified size");
|
|
return DW_ExprValueType_Generic;
|
|
}
|
|
|
|
internal DW_ExprValueType
|
|
dw_expr_signed_value_type_from_bit_size(U64 bit_size)
|
|
{
|
|
switch (bit_size) {
|
|
case 8: return DW_ExprValueType_S8;
|
|
case 16: return DW_ExprValueType_S16;
|
|
case 32: return DW_ExprValueType_S32;
|
|
case 64: return DW_ExprValueType_S64;
|
|
case 128: return DW_ExprValueType_S128;
|
|
case 256: return DW_ExprValueType_S256;
|
|
case 512: return DW_ExprValueType_S512;
|
|
}
|
|
AssertAlways(0 && "no suitable signed type was found for the specified size");
|
|
return DW_ExprValueType_Generic;
|
|
}
|
|
|
|
internal DW_ExprValueType
|
|
dw_expr_float_type_from_bit_size(U64 bit_size)
|
|
{
|
|
switch (bit_size) {
|
|
case 4: return DW_ExprValueType_F32;
|
|
case 8: return DW_ExprValueType_F64;
|
|
}
|
|
AssertAlways(0 && "no suitable type was found for the specified size");
|
|
return DW_ExprValueType_Generic;
|
|
}
|
|
|
|
internal U64
|
|
dw_expr_byte_size_from_value_type(U64 addr_size, DW_ExprValueType k)
|
|
{
|
|
switch (k) {
|
|
default: { InvalidPath; }
|
|
case DW_ExprValueType_Generic: return 0;
|
|
case DW_ExprValueType_Addr: return addr_size;
|
|
case DW_ExprValueType_U8: return 1;
|
|
case DW_ExprValueType_U16: return 2;
|
|
case DW_ExprValueType_U32: return 4;
|
|
case DW_ExprValueType_U64: return 8;
|
|
case DW_ExprValueType_U128: return 16;
|
|
case DW_ExprValueType_U256: return 32;
|
|
case DW_ExprValueType_U512: return 64;
|
|
case DW_ExprValueType_S8: return 1;
|
|
case DW_ExprValueType_S16: return 2;
|
|
case DW_ExprValueType_S32: return 4;
|
|
case DW_ExprValueType_S64: return 8;
|
|
case DW_ExprValueType_S128: return 16;
|
|
case DW_ExprValueType_S256: return 32;
|
|
case DW_ExprValueType_S512: return 64;
|
|
case DW_ExprValueType_F32: return 4;
|
|
case DW_ExprValueType_F64: return 8;
|
|
}
|
|
}
|
|
|
|
internal DW_ExprValueType
|
|
dw_expr_pick_common_value_type(DW_ExprValueType rhs, DW_ExprValueType lhs)
|
|
{
|
|
if (lhs == rhs) {
|
|
return lhs;
|
|
}
|
|
// unsigned vs unsigned
|
|
else if (DW_ExprValueType_IsUnsigned(lhs) && DW_ExprValueType_IsUnsigned(rhs)) {
|
|
return Max(lhs, rhs);
|
|
}
|
|
// signed vs signed
|
|
else if (DW_ExprValueType_IsSigned(lhs) && DW_ExprValueType_IsSigned(rhs)) {
|
|
return Max(lhs, rhs);
|
|
}
|
|
// (unsigned vs signed) || (signed vs unsigned)
|
|
else if ((DW_ExprValueType_IsUnsigned(lhs) && DW_ExprValueType_IsSigned(rhs)) ||
|
|
(DW_ExprValueType_IsSigned(lhs) && DW_ExprValueType_IsUnsigned(rhs))) {
|
|
U64 lhs_size = dw_expr_byte_size_from_value_type(0, lhs);
|
|
U64 rhs_size = dw_expr_byte_size_from_value_type(0, rhs);
|
|
if (lhs_size < rhs_size) {
|
|
return rhs;
|
|
} else if (lhs > rhs_size) {
|
|
return lhs;
|
|
} else {
|
|
return dw_expr_unsigned_value_type_from_bit_size(lhs_size * 8);
|
|
}
|
|
}
|
|
// float vs int
|
|
else if (DW_ExprValueType_IsFloat(lhs) && DW_ExprValueType_IsInt(rhs)) {
|
|
return lhs;
|
|
}
|
|
// int vs float
|
|
else if (DW_ExprValueType_IsInt(lhs) && DW_ExprValueType_IsFloat(rhs)) {
|
|
return rhs;
|
|
}
|
|
// float vs float
|
|
else if (DW_ExprValueType_IsFloat(lhs) && DW_ExprValueType_IsFloat(rhs)) {
|
|
return Max(lhs, rhs);
|
|
}
|
|
// address vs int
|
|
else if (lhs == DW_ExprValueType_Addr && DW_ExprValueType_IsInt(rhs)) {
|
|
return DW_ExprValueType_Addr;
|
|
}
|
|
// int vs address
|
|
else if (DW_ExprValueType_IsInt(lhs) && rhs == DW_ExprValueType_Addr) {
|
|
return DW_ExprValueType_Addr;
|
|
}
|
|
// address vs float
|
|
else if (lhs == DW_ExprValueType_Addr && DW_ExprValueType_IsFloat(rhs)) {
|
|
return DW_ExprValueType_Generic;
|
|
}
|
|
// float vs address
|
|
else if (DW_ExprValueType_IsFloat(lhs) && rhs == DW_ExprValueType_Addr) {
|
|
return DW_ExprValueType_Generic;
|
|
}
|
|
// no conversion for implicit value
|
|
else if (lhs == DW_ExprValueType_Implicit || rhs == DW_ExprValueType_Implicit) {
|
|
return DW_ExprValueType_Generic;
|
|
}
|
|
AssertAlways(!"undefined conversion case");
|
|
return DW_ExprValueType_Generic;
|
|
}
|
|
|
|
internal DW_ExprValueType
|
|
dw_expr_pick_common_compar_value_type(DW_ExprValueType rhs, DW_ExprValueType lhs)
|
|
{
|
|
DW_ExprValueType result;
|
|
if (lhs == DW_ExprValueType_Generic || rhs == DW_ExprValueType_Generic) {
|
|
result = DW_ExprValueType_S64;
|
|
} else {
|
|
result = dw_expr_pick_common_value_type(lhs, rhs);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
internal DW_ExprValue
|
|
dw_expr_cast(DW_ExprValue value, DW_ExprValueType type)
|
|
{
|
|
DW_ExprValue result = { type };
|
|
|
|
#define CastTable(f, t) \
|
|
switch (value.type) { \
|
|
case DW_ExprValueType_Generic: { MemoryCopy(&result.f, value.generic.str, Min(sizeof(t), value.generic.size)); } break; \
|
|
case DW_ExprValueType_U8: { result.f = (t)value.u8; } break; \
|
|
case DW_ExprValueType_U16: { result.f = (t)value.u16; } break; \
|
|
case DW_ExprValueType_U32: { result.f = (t)value.u32; } break; \
|
|
case DW_ExprValueType_U64: { result.f = (t)value.u64; } break; \
|
|
case DW_ExprValueType_U128: { NotImplemented; } break; \
|
|
case DW_ExprValueType_U256: { NotImplemented; } break; \
|
|
case DW_ExprValueType_U512: { NotImplemented; } break; \
|
|
case DW_ExprValueType_S8: { result.f = (t)value.s8; } break; \
|
|
case DW_ExprValueType_S16: { result.f = (t)value.s16; } break; \
|
|
case DW_ExprValueType_S32: { result.f = (t)value.s32; } break; \
|
|
case DW_ExprValueType_S64: { result.f = (t)value.s64; } break; \
|
|
case DW_ExprValueType_S128: { NotImplemented; } break; \
|
|
case DW_ExprValueType_S256: { NotImplemented; } break; \
|
|
case DW_ExprValueType_S512: { NotImplemented; } break; \
|
|
case DW_ExprValueType_F32: { result.f = (t)value.f32; } break; \
|
|
case DW_ExprValueType_F64: { result.f = (t)value.f64; } break; \
|
|
case DW_ExprValueType_Addr: { result.f = (t)value.addr; } break; \
|
|
case DW_ExprValueType_Implicit: { InvalidPath; } break; \
|
|
case DW_ExprValueType_Bool: { result.f = (t)value.boolean; } break; \
|
|
default: { InvalidPath; } break; \
|
|
}
|
|
|
|
switch (type) {
|
|
case DW_ExprValueType_Generic: {} break;
|
|
case DW_ExprValueType_U8: { CastTable(u8, U8); } break;
|
|
case DW_ExprValueType_U16: { CastTable(u16, U16); } break;
|
|
case DW_ExprValueType_U32: { CastTable(u32, U32); } break;
|
|
case DW_ExprValueType_U64: { CastTable(u64, U64); } break;
|
|
case DW_ExprValueType_U128: { NotImplemented; } break;
|
|
case DW_ExprValueType_U256: { NotImplemented; } break;
|
|
case DW_ExprValueType_U512: { NotImplemented; } break;
|
|
case DW_ExprValueType_S8: { CastTable(s8, S8); } break;
|
|
case DW_ExprValueType_S16: { CastTable(s16, S16); } break;
|
|
case DW_ExprValueType_S32: { CastTable(s32, S32); } break;
|
|
case DW_ExprValueType_S64: { CastTable(s64, S64); } break;
|
|
case DW_ExprValueType_S128: { NotImplemented; } break;
|
|
case DW_ExprValueType_S256: { NotImplemented; } break;
|
|
case DW_ExprValueType_S512: { NotImplemented; } break;
|
|
case DW_ExprValueType_F32: { CastTable(f32, F32); } break;
|
|
case DW_ExprValueType_F64: { CastTable(f64, F64); } break;
|
|
case DW_ExprValueType_Addr: { CastTable(addr, U64); } break;
|
|
case DW_ExprValueType_Implicit: { NotImplemented; } break;
|
|
case DW_ExprValueType_Bool: { CastTable(boolean, DW_ExprBool); } break;
|
|
}
|
|
|
|
#undef CastTable
|
|
return result;
|
|
}
|
|
|
|
internal DW_ExprValue
|
|
dw_expr_add(DW_ExprValue rhs, DW_ExprValue lhs)
|
|
{
|
|
DW_ExprValue result = {0};
|
|
result.type = dw_expr_pick_common_value_type(lhs.type, rhs.type);
|
|
|
|
DW_ExprValue common_lhs = dw_expr_cast(lhs, result.type);
|
|
DW_ExprValue common_rhs = dw_expr_cast(rhs, result.type);
|
|
|
|
switch (result.type) {
|
|
case DW_ExprValueType_Generic: { InvalidPath; } break;
|
|
|
|
case DW_ExprValueType_U8: { result.u8 = common_lhs.u8 + common_rhs.u8; } break;
|
|
case DW_ExprValueType_U16: { result.u16 = common_lhs.u16 + common_rhs.u16; } break;
|
|
case DW_ExprValueType_U32: { result.u32 = common_lhs.u32 + common_rhs.u32; } break;
|
|
case DW_ExprValueType_U64: { result.u64 = common_lhs.u64 + common_rhs.u64; } break;
|
|
|
|
case DW_ExprValueType_U128:
|
|
case DW_ExprValueType_U256:
|
|
case DW_ExprValueType_U512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_Bool: { result.s8 = common_lhs.s8 + common_rhs.s8; } break;
|
|
case DW_ExprValueType_S8: { result.s8 = common_lhs.s8 + common_rhs.s8; } break;
|
|
case DW_ExprValueType_S16: { result.s16 = common_lhs.s16 + common_rhs.s16; } break;
|
|
case DW_ExprValueType_S32: { result.s32 = common_lhs.s32 + common_rhs.s32; } break;
|
|
case DW_ExprValueType_S64: { result.s64 = common_lhs.s64 + common_rhs.s64; } break;
|
|
|
|
case DW_ExprValueType_S128:
|
|
case DW_ExprValueType_S256:
|
|
case DW_ExprValueType_S512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_F32: { result.f32 = common_lhs.f32 + common_rhs.f32; } break;
|
|
case DW_ExprValueType_F64: { result.f64 = common_lhs.f64 + common_rhs.f64; } break;
|
|
case DW_ExprValueType_Addr: { result.addr = common_lhs.addr + common_rhs.addr; } break;
|
|
case DW_ExprValueType_Implicit: { InvalidPath; } break;
|
|
|
|
default: { InvalidPath; } break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
internal DW_ExprValue
|
|
dw_expr_minus(DW_ExprValue rhs, DW_ExprValue lhs)
|
|
{
|
|
DW_ExprValue result = {0};
|
|
result.type = dw_expr_pick_common_value_type(lhs.type, rhs.type);
|
|
|
|
DW_ExprValue common_lhs = dw_expr_cast(lhs, result.type);
|
|
DW_ExprValue common_rhs = dw_expr_cast(rhs, result.type);
|
|
|
|
switch (result.type) {
|
|
case DW_ExprValueType_Generic: { InvalidPath; } break;
|
|
|
|
case DW_ExprValueType_U8: { result.u8 = common_lhs.u8 - common_rhs.u8; } break;
|
|
case DW_ExprValueType_U16: { result.u16 = common_lhs.u16 - common_rhs.u16; } break;
|
|
case DW_ExprValueType_U32: { result.u32 = common_lhs.u32 - common_rhs.u32; } break;
|
|
case DW_ExprValueType_U64: { result.u64 = common_lhs.u64 - common_rhs.u64; } break;
|
|
|
|
case DW_ExprValueType_U128:
|
|
case DW_ExprValueType_U256:
|
|
case DW_ExprValueType_U512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_Bool: { result.s8 = common_lhs.s8 - common_rhs.s8; } break;
|
|
case DW_ExprValueType_S8: { result.s8 = common_lhs.s8 - common_rhs.s8; } break;
|
|
case DW_ExprValueType_S16: { result.s16 = common_lhs.s16 - common_rhs.s16; } break;
|
|
case DW_ExprValueType_S32: { result.s32 = common_lhs.s32 - common_rhs.s32; } break;
|
|
case DW_ExprValueType_S64: { result.s64 = common_lhs.s64 - common_rhs.s64; } break;
|
|
|
|
case DW_ExprValueType_S128:
|
|
case DW_ExprValueType_S256:
|
|
case DW_ExprValueType_S512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_F32: { result.f32 = common_lhs.f32 - common_rhs.f32; } break;
|
|
case DW_ExprValueType_F64: { result.f64 = common_lhs.f64 - common_rhs.f64; } break;
|
|
case DW_ExprValueType_Addr: { result.addr = common_lhs.addr - common_rhs.addr; } break;
|
|
case DW_ExprValueType_Implicit: { InvalidPath; } break;
|
|
|
|
default: { InvalidPath; } break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
internal DW_ExprValue
|
|
dw_expr_mul(DW_ExprValue rhs, DW_ExprValue lhs)
|
|
{
|
|
DW_ExprValue result = {0};
|
|
result.type = dw_expr_pick_common_value_type(lhs.type, rhs.type);
|
|
|
|
DW_ExprValue common_lhs = dw_expr_cast(lhs, result.type);
|
|
DW_ExprValue common_rhs = dw_expr_cast(rhs, result.type);
|
|
|
|
switch (result.type) {
|
|
case DW_ExprValueType_Generic: { InvalidPath; } break;
|
|
|
|
case DW_ExprValueType_U8: { result.u8 = common_lhs.u8 * common_rhs.u8; } break;
|
|
case DW_ExprValueType_U16: { result.u16 = common_lhs.u16 * common_rhs.u16; } break;
|
|
case DW_ExprValueType_U32: { result.u32 = common_lhs.u32 * common_rhs.u32; } break;
|
|
case DW_ExprValueType_U64: { result.u64 = common_lhs.u64 * common_rhs.u64; } break;
|
|
|
|
case DW_ExprValueType_U128:
|
|
case DW_ExprValueType_U256:
|
|
case DW_ExprValueType_U512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_Bool: { result.s8 = common_lhs.s8 * common_rhs.s8; } break;
|
|
case DW_ExprValueType_S8: { result.s8 = common_lhs.s8 * common_rhs.s8; } break;
|
|
case DW_ExprValueType_S16: { result.s16 = common_lhs.s16 * common_rhs.s16; } break;
|
|
case DW_ExprValueType_S32: { result.s32 = common_lhs.s32 * common_rhs.s32; } break;
|
|
case DW_ExprValueType_S64: { result.s64 = common_lhs.s64 * common_rhs.s64; } break;
|
|
|
|
case DW_ExprValueType_S128:
|
|
case DW_ExprValueType_S256:
|
|
case DW_ExprValueType_S512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_F32: { result.f32 = common_lhs.f32 * common_rhs.f32; } break;
|
|
case DW_ExprValueType_F64: { result.f64 = common_lhs.f64 * common_rhs.f64; } break;
|
|
case DW_ExprValueType_Addr: { result.addr = common_lhs.addr * common_rhs.addr; } break;
|
|
case DW_ExprValueType_Implicit: { InvalidPath; } break;
|
|
|
|
default: { InvalidPath; } break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
internal DW_ExprValue
|
|
dw_expr_div(DW_ExprValue rhs, DW_ExprValue lhs)
|
|
{
|
|
DW_ExprValue result = {0};
|
|
result.type = dw_expr_pick_common_value_type(lhs.type, rhs.type);
|
|
|
|
DW_ExprValue common_lhs = dw_expr_cast(lhs, result.type);
|
|
DW_ExprValue common_rhs = dw_expr_cast(rhs, result.type);
|
|
|
|
switch (result.type) {
|
|
case DW_ExprValueType_Generic: { InvalidPath; } break;
|
|
|
|
case DW_ExprValueType_U8: { result.u8 = common_lhs.u8 / common_rhs.u8; } break;
|
|
case DW_ExprValueType_U16: { result.u16 = common_lhs.u16 / common_rhs.u16; } break;
|
|
case DW_ExprValueType_U32: { result.u32 = common_lhs.u32 / common_rhs.u32; } break;
|
|
case DW_ExprValueType_U64: { result.u64 = common_lhs.u64 / common_rhs.u64; } break;
|
|
|
|
case DW_ExprValueType_U128:
|
|
case DW_ExprValueType_U256:
|
|
case DW_ExprValueType_U512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_Bool: { result.s8 = common_lhs.s8 / common_rhs.s8; } break;
|
|
case DW_ExprValueType_S8: { result.s8 = common_lhs.s8 / common_rhs.s8; } break;
|
|
case DW_ExprValueType_S16: { result.s16 = common_lhs.s16 / common_rhs.s16; } break;
|
|
case DW_ExprValueType_S32: { result.s32 = common_lhs.s32 / common_rhs.s32; } break;
|
|
case DW_ExprValueType_S64: { result.s64 = common_lhs.s64 / common_rhs.s64; } break;
|
|
|
|
case DW_ExprValueType_S128:
|
|
case DW_ExprValueType_S256:
|
|
case DW_ExprValueType_S512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_F32: { result.f32 = common_lhs.f32 / common_rhs.f32; } break;
|
|
case DW_ExprValueType_F64: { result.f64 = common_lhs.f64 / common_rhs.f64; } break;
|
|
case DW_ExprValueType_Addr: { result.addr = common_lhs.addr / common_rhs.addr; } break;
|
|
case DW_ExprValueType_Implicit: { InvalidPath; } break;
|
|
|
|
default: { InvalidPath; } break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
internal DW_ExprValue
|
|
dw_expr_mod(DW_ExprValue rhs, DW_ExprValue lhs)
|
|
{
|
|
DW_ExprValue result = {0};
|
|
result.type = dw_expr_pick_common_value_type(lhs.type, rhs.type);
|
|
|
|
DW_ExprValue common_lhs = dw_expr_cast(lhs, result.type);
|
|
DW_ExprValue common_rhs = dw_expr_cast(rhs, result.type);
|
|
|
|
switch (result.type) {
|
|
case DW_ExprValueType_Generic: { InvalidPath; } break;
|
|
|
|
case DW_ExprValueType_U8: { result.u8 = common_lhs.u8 % common_rhs.u8; } break;
|
|
case DW_ExprValueType_U16: { result.u16 = common_lhs.u16 % common_rhs.u16; } break;
|
|
case DW_ExprValueType_U32: { result.u32 = common_lhs.u32 % common_rhs.u32; } break;
|
|
case DW_ExprValueType_U64: { result.u64 = common_lhs.u64 % common_rhs.u64; } break;
|
|
|
|
case DW_ExprValueType_U128:
|
|
case DW_ExprValueType_U256:
|
|
case DW_ExprValueType_U512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_Bool: { result.s8 = common_lhs.s8 % common_rhs.s8; } break;
|
|
case DW_ExprValueType_S8: { result.s8 = common_lhs.s8 % common_rhs.s8; } break;
|
|
case DW_ExprValueType_S16: { result.s16 = common_lhs.s16 % common_rhs.s16; } break;
|
|
case DW_ExprValueType_S32: { result.s32 = common_lhs.s32 % common_rhs.s32; } break;
|
|
case DW_ExprValueType_S64: { result.s64 = common_lhs.s64 % common_rhs.s64; } break;
|
|
|
|
case DW_ExprValueType_S128:
|
|
case DW_ExprValueType_S256:
|
|
case DW_ExprValueType_S512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_F32: { InvalidPath; } break;
|
|
case DW_ExprValueType_F64: { InvalidPath; } break;
|
|
case DW_ExprValueType_Addr: { result.addr = common_lhs.addr % common_rhs.addr; } break;
|
|
case DW_ExprValueType_Implicit: { InvalidPath; } break;
|
|
|
|
default: { InvalidPath; } break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
internal DW_ExprValue
|
|
dw_expr_eq(DW_ExprValue rhs, DW_ExprValue lhs)
|
|
{
|
|
DW_ExprValue result = {0};
|
|
result.type = dw_expr_pick_common_compar_value_type(lhs.type, rhs.type);
|
|
|
|
DW_ExprValue common_lhs = dw_expr_cast(lhs, result.type);
|
|
DW_ExprValue common_rhs = dw_expr_cast(rhs, result.type);
|
|
|
|
switch (result.type) {
|
|
case DW_ExprValueType_Generic: { InvalidPath; } break;
|
|
|
|
case DW_ExprValueType_U8: { result.u8 = common_lhs.u8 == common_rhs.u8; } break;
|
|
case DW_ExprValueType_U16: { result.u16 = common_lhs.u16 == common_rhs.u16; } break;
|
|
case DW_ExprValueType_U32: { result.u32 = common_lhs.u32 == common_rhs.u32; } break;
|
|
case DW_ExprValueType_U64: { result.u64 = common_lhs.u64 == common_rhs.u64; } break;
|
|
|
|
case DW_ExprValueType_U128:
|
|
case DW_ExprValueType_U256:
|
|
case DW_ExprValueType_U512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_Bool: { result.s8 = common_lhs.s8 == common_rhs.s8; } break;
|
|
case DW_ExprValueType_S8: { result.s8 = common_lhs.s8 == common_rhs.s8; } break;
|
|
case DW_ExprValueType_S16: { result.s16 = common_lhs.s16 == common_rhs.s16; } break;
|
|
case DW_ExprValueType_S32: { result.s32 = common_lhs.s32 == common_rhs.s32; } break;
|
|
case DW_ExprValueType_S64: { result.s64 = common_lhs.s64 == common_rhs.s64; } break;
|
|
|
|
case DW_ExprValueType_S128:
|
|
case DW_ExprValueType_S256:
|
|
case DW_ExprValueType_S512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_F32: { result.f32 = common_lhs.f32 == common_rhs.f32; } break;
|
|
case DW_ExprValueType_F64: { result.f64 = common_lhs.f64 == common_rhs.f64; } break;
|
|
case DW_ExprValueType_Addr: { result.addr = common_lhs.addr == common_rhs.addr; } break;
|
|
case DW_ExprValueType_Implicit: { InvalidPath; } break;
|
|
|
|
default: { InvalidPath; } break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
internal DW_ExprValue
|
|
dw_expr_ge(DW_ExprValue rhs, DW_ExprValue lhs)
|
|
{
|
|
DW_ExprValue result = {0};
|
|
result.type = dw_expr_pick_common_compar_value_type(lhs.type, rhs.type);
|
|
|
|
DW_ExprValue common_lhs = dw_expr_cast(lhs, result.type);
|
|
DW_ExprValue common_rhs = dw_expr_cast(rhs, result.type);
|
|
|
|
switch (result.type) {
|
|
case DW_ExprValueType_Generic: { InvalidPath; } break;
|
|
|
|
case DW_ExprValueType_U8: { result.u8 = common_lhs.u8 >= common_rhs.u8; } break;
|
|
case DW_ExprValueType_U16: { result.u16 = common_lhs.u16 >= common_rhs.u16; } break;
|
|
case DW_ExprValueType_U32: { result.u32 = common_lhs.u32 >= common_rhs.u32; } break;
|
|
case DW_ExprValueType_U64: { result.u64 = common_lhs.u64 >= common_rhs.u64; } break;
|
|
|
|
case DW_ExprValueType_U128:
|
|
case DW_ExprValueType_U256:
|
|
case DW_ExprValueType_U512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_Bool: { result.s8 = common_lhs.s8 >= common_rhs.s8; } break;
|
|
case DW_ExprValueType_S8: { result.s8 = common_lhs.s8 >= common_rhs.s8; } break;
|
|
case DW_ExprValueType_S16: { result.s16 = common_lhs.s16 >= common_rhs.s16; } break;
|
|
case DW_ExprValueType_S32: { result.s32 = common_lhs.s32 >= common_rhs.s32; } break;
|
|
case DW_ExprValueType_S64: { result.s64 = common_lhs.s64 >= common_rhs.s64; } break;
|
|
|
|
case DW_ExprValueType_S128:
|
|
case DW_ExprValueType_S256:
|
|
case DW_ExprValueType_S512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_F32: { result.f32 = common_lhs.f32 >= common_rhs.f32; } break;
|
|
case DW_ExprValueType_F64: { result.f64 = common_lhs.f64 >= common_rhs.f64; } break;
|
|
case DW_ExprValueType_Addr: { result.addr = common_lhs.addr >= common_rhs.addr; } break;
|
|
case DW_ExprValueType_Implicit: { InvalidPath; } break;
|
|
|
|
default: { InvalidPath; } break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
internal DW_ExprValue
|
|
dw_expr_gt(DW_ExprValue rhs, DW_ExprValue lhs)
|
|
{
|
|
DW_ExprValue result = {0};
|
|
result.type = dw_expr_pick_common_compar_value_type(lhs.type, rhs.type);
|
|
|
|
DW_ExprValue common_lhs = dw_expr_cast(lhs, result.type);
|
|
DW_ExprValue common_rhs = dw_expr_cast(rhs, result.type);
|
|
|
|
switch (result.type) {
|
|
case DW_ExprValueType_Generic: { InvalidPath; } break;
|
|
|
|
case DW_ExprValueType_U8: { result.u8 = common_lhs.u8 > common_rhs.u8; } break;
|
|
case DW_ExprValueType_U16: { result.u16 = common_lhs.u16 > common_rhs.u16; } break;
|
|
case DW_ExprValueType_U32: { result.u32 = common_lhs.u32 > common_rhs.u32; } break;
|
|
case DW_ExprValueType_U64: { result.u64 = common_lhs.u64 > common_rhs.u64; } break;
|
|
|
|
case DW_ExprValueType_U128:
|
|
case DW_ExprValueType_U256:
|
|
case DW_ExprValueType_U512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_Bool: { result.s8 = common_lhs.s8 > common_rhs.s8; } break;
|
|
case DW_ExprValueType_S8: { result.s8 = common_lhs.s8 > common_rhs.s8; } break;
|
|
case DW_ExprValueType_S16: { result.s16 = common_lhs.s16 > common_rhs.s16; } break;
|
|
case DW_ExprValueType_S32: { result.s32 = common_lhs.s32 > common_rhs.s32; } break;
|
|
case DW_ExprValueType_S64: { result.s64 = common_lhs.s64 > common_rhs.s64; } break;
|
|
|
|
case DW_ExprValueType_S128:
|
|
case DW_ExprValueType_S256:
|
|
case DW_ExprValueType_S512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_F32: { result.f32 = common_lhs.f32 > common_rhs.f32; } break;
|
|
case DW_ExprValueType_F64: { result.f64 = common_lhs.f64 > common_rhs.f64; } break;
|
|
case DW_ExprValueType_Addr: { result.addr = common_lhs.addr > common_rhs.addr; } break;
|
|
case DW_ExprValueType_Implicit: { InvalidPath; } break;
|
|
|
|
default: { InvalidPath; } break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
internal DW_ExprValue
|
|
dw_expr_le(DW_ExprValue rhs, DW_ExprValue lhs)
|
|
{
|
|
DW_ExprValue result = {0};
|
|
result.type = dw_expr_pick_common_compar_value_type(lhs.type, rhs.type);
|
|
|
|
DW_ExprValue common_lhs = dw_expr_cast(lhs, result.type);
|
|
DW_ExprValue common_rhs = dw_expr_cast(rhs, result.type);
|
|
|
|
switch (result.type) {
|
|
case DW_ExprValueType_Generic: { InvalidPath; } break;
|
|
|
|
case DW_ExprValueType_U8: { result.u8 = common_lhs.u8 <= common_rhs.u8; } break;
|
|
case DW_ExprValueType_U16: { result.u16 = common_lhs.u16 <= common_rhs.u16; } break;
|
|
case DW_ExprValueType_U32: { result.u32 = common_lhs.u32 <= common_rhs.u32; } break;
|
|
case DW_ExprValueType_U64: { result.u64 = common_lhs.u64 <= common_rhs.u64; } break;
|
|
|
|
case DW_ExprValueType_U128:
|
|
case DW_ExprValueType_U256:
|
|
case DW_ExprValueType_U512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_Bool: { result.s8 = common_lhs.s8 <= common_rhs.s8; } break;
|
|
case DW_ExprValueType_S8: { result.s8 = common_lhs.s8 <= common_rhs.s8; } break;
|
|
case DW_ExprValueType_S16: { result.s16 = common_lhs.s16 <= common_rhs.s16; } break;
|
|
case DW_ExprValueType_S32: { result.s32 = common_lhs.s32 <= common_rhs.s32; } break;
|
|
case DW_ExprValueType_S64: { result.s64 = common_lhs.s64 <= common_rhs.s64; } break;
|
|
|
|
case DW_ExprValueType_S128:
|
|
case DW_ExprValueType_S256:
|
|
case DW_ExprValueType_S512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_F32: { result.f32 = common_lhs.f32 <= common_rhs.f32; } break;
|
|
case DW_ExprValueType_F64: { result.f64 = common_lhs.f64 <= common_rhs.f64; } break;
|
|
case DW_ExprValueType_Addr: { result.addr = common_lhs.addr <= common_rhs.addr; } break;
|
|
case DW_ExprValueType_Implicit: { InvalidPath; } break;
|
|
|
|
default: { InvalidPath; } break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
internal DW_ExprValue
|
|
dw_expr_lt(DW_ExprValue rhs, DW_ExprValue lhs)
|
|
{
|
|
DW_ExprValue result = {0};
|
|
result.type = dw_expr_pick_common_compar_value_type(lhs.type, rhs.type);
|
|
|
|
DW_ExprValue common_lhs = dw_expr_cast(lhs, result.type);
|
|
DW_ExprValue common_rhs = dw_expr_cast(rhs, result.type);
|
|
|
|
switch (result.type) {
|
|
case DW_ExprValueType_Generic: { InvalidPath; } break;
|
|
|
|
case DW_ExprValueType_U8: { result.u8 = common_lhs.u8 < common_rhs.u8; } break;
|
|
case DW_ExprValueType_U16: { result.u16 = common_lhs.u16 < common_rhs.u16; } break;
|
|
case DW_ExprValueType_U32: { result.u32 = common_lhs.u32 < common_rhs.u32; } break;
|
|
case DW_ExprValueType_U64: { result.u64 = common_lhs.u64 < common_rhs.u64; } break;
|
|
|
|
case DW_ExprValueType_U128:
|
|
case DW_ExprValueType_U256:
|
|
case DW_ExprValueType_U512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_Bool: { result.s8 = common_lhs.s8 < common_rhs.s8; } break;
|
|
case DW_ExprValueType_S8: { result.s8 = common_lhs.s8 < common_rhs.s8; } break;
|
|
case DW_ExprValueType_S16: { result.s16 = common_lhs.s16 < common_rhs.s16; } break;
|
|
case DW_ExprValueType_S32: { result.s32 = common_lhs.s32 < common_rhs.s32; } break;
|
|
case DW_ExprValueType_S64: { result.s64 = common_lhs.s64 < common_rhs.s64; } break;
|
|
|
|
case DW_ExprValueType_S128:
|
|
case DW_ExprValueType_S256:
|
|
case DW_ExprValueType_S512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_F32: { result.f32 = common_lhs.f32 < common_rhs.f32; } break;
|
|
case DW_ExprValueType_F64: { result.f64 = common_lhs.f64 < common_rhs.f64; } break;
|
|
case DW_ExprValueType_Addr: { result.addr = common_lhs.addr < common_rhs.addr; } break;
|
|
case DW_ExprValueType_Implicit: { InvalidPath; } break;
|
|
|
|
default: { InvalidPath; } break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
internal DW_ExprValue
|
|
dw_expr_ne(DW_ExprValue rhs, DW_ExprValue lhs)
|
|
{
|
|
DW_ExprValue result = {0};
|
|
result.type = dw_expr_pick_common_compar_value_type(lhs.type, rhs.type);
|
|
|
|
DW_ExprValue common_lhs = dw_expr_cast(lhs, result.type);
|
|
DW_ExprValue common_rhs = dw_expr_cast(rhs, result.type);
|
|
|
|
switch (result.type) {
|
|
case DW_ExprValueType_Generic: { InvalidPath; } break;
|
|
|
|
case DW_ExprValueType_U8: { result.u8 = common_lhs.u8 != common_rhs.u8; } break;
|
|
case DW_ExprValueType_U16: { result.u16 = common_lhs.u16 != common_rhs.u16; } break;
|
|
case DW_ExprValueType_U32: { result.u32 = common_lhs.u32 != common_rhs.u32; } break;
|
|
case DW_ExprValueType_U64: { result.u64 = common_lhs.u64 != common_rhs.u64; } break;
|
|
|
|
case DW_ExprValueType_U128:
|
|
case DW_ExprValueType_U256:
|
|
case DW_ExprValueType_U512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_Bool: { result.s8 = common_lhs.s8 != common_rhs.s8; } break;
|
|
case DW_ExprValueType_S8: { result.s8 = common_lhs.s8 != common_rhs.s8; } break;
|
|
case DW_ExprValueType_S16: { result.s16 = common_lhs.s16 != common_rhs.s16; } break;
|
|
case DW_ExprValueType_S32: { result.s32 = common_lhs.s32 != common_rhs.s32; } break;
|
|
case DW_ExprValueType_S64: { result.s64 = common_lhs.s64 != common_rhs.s64; } break;
|
|
|
|
case DW_ExprValueType_S128:
|
|
case DW_ExprValueType_S256:
|
|
case DW_ExprValueType_S512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_F32: { result.f32 = common_lhs.f32 != common_rhs.f32; } break;
|
|
case DW_ExprValueType_F64: { result.f64 = common_lhs.f64 != common_rhs.f64; } break;
|
|
case DW_ExprValueType_Addr: { result.addr = common_lhs.addr != common_rhs.addr; } break;
|
|
case DW_ExprValueType_Implicit: { InvalidPath; } break;
|
|
|
|
default: { InvalidPath; } break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
internal DW_ExprValue
|
|
dw_expr_xor(DW_ExprValue rhs, DW_ExprValue lhs)
|
|
{
|
|
DW_ExprValue result = {0};
|
|
result.type = dw_expr_pick_common_compar_value_type(lhs.type, rhs.type);
|
|
|
|
DW_ExprValue common_lhs = dw_expr_cast(lhs, result.type);
|
|
DW_ExprValue common_rhs = dw_expr_cast(rhs, result.type);
|
|
|
|
switch (result.type) {
|
|
case DW_ExprValueType_Generic: { InvalidPath; } break;
|
|
|
|
case DW_ExprValueType_U8: { result.u8 = common_lhs.u8 ^ common_rhs.u8; } break;
|
|
case DW_ExprValueType_U16: { result.u16 = common_lhs.u16 ^ common_rhs.u16; } break;
|
|
case DW_ExprValueType_U32: { result.u32 = common_lhs.u32 ^ common_rhs.u32; } break;
|
|
case DW_ExprValueType_U64: { result.u64 = common_lhs.u64 ^ common_rhs.u64; } break;
|
|
|
|
case DW_ExprValueType_U128:
|
|
case DW_ExprValueType_U256:
|
|
case DW_ExprValueType_U512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_Bool: { result.s8 = common_lhs.s8 ^ common_rhs.s8; } break;
|
|
case DW_ExprValueType_S8: { result.s8 = common_lhs.s8 ^ common_rhs.s8; } break;
|
|
case DW_ExprValueType_S16: { result.s16 = common_lhs.s16 ^ common_rhs.s16; } break;
|
|
case DW_ExprValueType_S32: { result.s32 = common_lhs.s32 ^ common_rhs.s32; } break;
|
|
case DW_ExprValueType_S64: { result.s64 = common_lhs.s64 ^ common_rhs.s64; } break;
|
|
|
|
case DW_ExprValueType_S128:
|
|
case DW_ExprValueType_S256:
|
|
case DW_ExprValueType_S512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_F32: { InvalidPath; } break;
|
|
case DW_ExprValueType_F64: { InvalidPath; } break;
|
|
case DW_ExprValueType_Addr: { result.addr = common_lhs.addr ^ common_rhs.addr; } break;
|
|
case DW_ExprValueType_Implicit: { InvalidPath; } break;
|
|
|
|
default: { InvalidPath; } break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
internal DW_ExprValue
|
|
dw_expr_and(DW_ExprValue rhs, DW_ExprValue lhs)
|
|
{
|
|
DW_ExprValue result = {0};
|
|
result.type = dw_expr_pick_common_compar_value_type(lhs.type, rhs.type);
|
|
|
|
DW_ExprValue common_lhs = dw_expr_cast(lhs, result.type);
|
|
DW_ExprValue common_rhs = dw_expr_cast(rhs, result.type);
|
|
|
|
switch (result.type) {
|
|
case DW_ExprValueType_Generic: { InvalidPath; } break;
|
|
|
|
case DW_ExprValueType_U8: { result.u8 = common_lhs.u8 & common_rhs.u8; } break;
|
|
case DW_ExprValueType_U16: { result.u16 = common_lhs.u16 & common_rhs.u16; } break;
|
|
case DW_ExprValueType_U32: { result.u32 = common_lhs.u32 & common_rhs.u32; } break;
|
|
case DW_ExprValueType_U64: { result.u64 = common_lhs.u64 & common_rhs.u64; } break;
|
|
|
|
case DW_ExprValueType_U128:
|
|
case DW_ExprValueType_U256:
|
|
case DW_ExprValueType_U512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_Bool: { result.s8 = common_lhs.s8 & common_rhs.s8; } break;
|
|
case DW_ExprValueType_S8: { result.s8 = common_lhs.s8 & common_rhs.s8; } break;
|
|
case DW_ExprValueType_S16: { result.s16 = common_lhs.s16 & common_rhs.s16; } break;
|
|
case DW_ExprValueType_S32: { result.s32 = common_lhs.s32 & common_rhs.s32; } break;
|
|
case DW_ExprValueType_S64: { result.s64 = common_lhs.s64 & common_rhs.s64; } break;
|
|
|
|
case DW_ExprValueType_S128:
|
|
case DW_ExprValueType_S256:
|
|
case DW_ExprValueType_S512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_F32: { InvalidPath; } break;
|
|
case DW_ExprValueType_F64: { InvalidPath; } break;
|
|
case DW_ExprValueType_Addr: { result.addr = common_lhs.addr & common_rhs.addr; } break;
|
|
case DW_ExprValueType_Implicit: { InvalidPath; } break;
|
|
|
|
default: { InvalidPath; } break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
internal DW_ExprValue
|
|
dw_expr_or(DW_ExprValue rhs, DW_ExprValue lhs)
|
|
{
|
|
DW_ExprValue result = {0};
|
|
result.type = dw_expr_pick_common_compar_value_type(lhs.type, rhs.type);
|
|
|
|
DW_ExprValue common_lhs = dw_expr_cast(lhs, result.type);
|
|
DW_ExprValue common_rhs = dw_expr_cast(rhs, result.type);
|
|
|
|
switch (result.type) {
|
|
case DW_ExprValueType_Generic: { InvalidPath; } break;
|
|
|
|
case DW_ExprValueType_U8: { result.u8 = common_lhs.u8 | common_rhs.u8; } break;
|
|
case DW_ExprValueType_U16: { result.u16 = common_lhs.u16 | common_rhs.u16; } break;
|
|
case DW_ExprValueType_U32: { result.u32 = common_lhs.u32 | common_rhs.u32; } break;
|
|
case DW_ExprValueType_U64: { result.u64 = common_lhs.u64 | common_rhs.u64; } break;
|
|
|
|
case DW_ExprValueType_U128:
|
|
case DW_ExprValueType_U256:
|
|
case DW_ExprValueType_U512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_Bool: { result.s8 = common_lhs.s8 | common_rhs.s8; } break;
|
|
case DW_ExprValueType_S8: { result.s8 = common_lhs.s8 | common_rhs.s8; } break;
|
|
case DW_ExprValueType_S16: { result.s16 = common_lhs.s16 | common_rhs.s16; } break;
|
|
case DW_ExprValueType_S32: { result.s32 = common_lhs.s32 | common_rhs.s32; } break;
|
|
case DW_ExprValueType_S64: { result.s64 = common_lhs.s64 | common_rhs.s64; } break;
|
|
|
|
case DW_ExprValueType_S128:
|
|
case DW_ExprValueType_S256:
|
|
case DW_ExprValueType_S512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_F32: { InvalidPath; } break;
|
|
case DW_ExprValueType_F64: { InvalidPath; } break;
|
|
case DW_ExprValueType_Addr: { result.addr = common_lhs.addr | common_rhs.addr; } break;
|
|
case DW_ExprValueType_Implicit: { InvalidPath; } break;
|
|
|
|
default: { InvalidPath; } break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
internal DW_ExprValue
|
|
dw_expr_shl(DW_ExprValue rhs, DW_ExprValue lhs)
|
|
{
|
|
DW_ExprValue result = {0};
|
|
result.type = dw_expr_pick_common_compar_value_type(lhs.type, rhs.type);
|
|
|
|
DW_ExprValue common_lhs = dw_expr_cast(lhs, result.type);
|
|
DW_ExprValue common_rhs = dw_expr_cast(rhs, result.type);
|
|
|
|
switch (result.type) {
|
|
case DW_ExprValueType_Generic: { InvalidPath; } break;
|
|
|
|
case DW_ExprValueType_U8: { result.u8 = common_lhs.u8 << common_rhs.u8; } break;
|
|
case DW_ExprValueType_U16: { result.u16 = common_lhs.u16 << common_rhs.u16; } break;
|
|
case DW_ExprValueType_U32: { result.u32 = common_lhs.u32 << common_rhs.u32; } break;
|
|
case DW_ExprValueType_U64: { result.u64 = common_lhs.u64 << common_rhs.u64; } break;
|
|
|
|
case DW_ExprValueType_U128:
|
|
case DW_ExprValueType_U256:
|
|
case DW_ExprValueType_U512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_Bool: { result.s8 = common_lhs.s8 << common_rhs.s8; } break;
|
|
case DW_ExprValueType_S8: { result.s8 = common_lhs.s8 << common_rhs.s8; } break;
|
|
case DW_ExprValueType_S16: { result.s16 = common_lhs.s16 << common_rhs.s16; } break;
|
|
case DW_ExprValueType_S32: { result.s32 = common_lhs.s32 << common_rhs.s32; } break;
|
|
case DW_ExprValueType_S64: { result.s64 = common_lhs.s64 << common_rhs.s64; } break;
|
|
|
|
case DW_ExprValueType_S128:
|
|
case DW_ExprValueType_S256:
|
|
case DW_ExprValueType_S512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_F32: { InvalidPath; } break;
|
|
case DW_ExprValueType_F64: { InvalidPath; } break;
|
|
case DW_ExprValueType_Addr: { result.addr = common_lhs.addr << common_rhs.addr; } break;
|
|
case DW_ExprValueType_Implicit: { InvalidPath; } break;
|
|
|
|
default: { InvalidPath; } break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
internal DW_ExprValue
|
|
dw_expr_shr(DW_ExprValue rhs, DW_ExprValue lhs)
|
|
{
|
|
DW_ExprValue result = {0};
|
|
result.type = dw_expr_pick_common_compar_value_type(lhs.type, rhs.type);
|
|
|
|
DW_ExprValue common_lhs = dw_expr_cast(lhs, result.type);
|
|
DW_ExprValue common_rhs = dw_expr_cast(rhs, result.type);
|
|
|
|
switch (result.type) {
|
|
case DW_ExprValueType_Generic: { InvalidPath; } break;
|
|
|
|
case DW_ExprValueType_U8: { result.u8 = common_lhs.u8 >> common_rhs.u8; } break;
|
|
case DW_ExprValueType_U16: { result.u16 = common_lhs.u16 >> common_rhs.u16; } break;
|
|
case DW_ExprValueType_U32: { result.u32 = common_lhs.u32 >> common_rhs.u32; } break;
|
|
case DW_ExprValueType_U64: { result.u64 = common_lhs.u64 >> common_rhs.u64; } break;
|
|
|
|
case DW_ExprValueType_U128: { NotImplemented; } break;
|
|
case DW_ExprValueType_U256: { NotImplemented; } break;
|
|
case DW_ExprValueType_U512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_Bool: { InvalidPath; } break;
|
|
case DW_ExprValueType_S8: { InvalidPath; } break;
|
|
case DW_ExprValueType_S16: { InvalidPath; } break;
|
|
case DW_ExprValueType_S32: { InvalidPath; } break;
|
|
case DW_ExprValueType_S64: { InvalidPath; } break;
|
|
case DW_ExprValueType_S128: { InvalidPath; } break;
|
|
case DW_ExprValueType_S256: { InvalidPath; } break;
|
|
case DW_ExprValueType_S512: { InvalidPath; } break;
|
|
|
|
case DW_ExprValueType_F32: { InvalidPath; } break;
|
|
case DW_ExprValueType_F64: { InvalidPath; } break;
|
|
case DW_ExprValueType_Addr: { result.addr = common_lhs.addr >> common_rhs.addr; } break;
|
|
case DW_ExprValueType_Implicit: { InvalidPath; } break;
|
|
|
|
default: { InvalidPath; } break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
internal DW_ExprValue
|
|
dw_expr_shra(DW_ExprValue rhs, DW_ExprValue lhs)
|
|
{
|
|
if (DW_ExprValueType_IsUnsigned(lhs.type)) {
|
|
DW_ExprValueType new_type = dw_expr_signed_value_type_from_bit_size(dw_expr_byte_size_from_value_type(0, lhs.type) * 8);
|
|
lhs = dw_expr_cast(lhs, new_type);
|
|
}
|
|
|
|
if (DW_ExprValueType_IsUnsigned(rhs.type)) {
|
|
DW_ExprValueType new_type = dw_expr_signed_value_type_from_bit_size(dw_expr_byte_size_from_value_type(0, rhs.type) * 8);
|
|
rhs = dw_expr_cast(rhs, new_type);
|
|
}
|
|
|
|
DW_ExprValue result = {0};
|
|
result.type = dw_expr_pick_common_compar_value_type(lhs.type, rhs.type);
|
|
|
|
DW_ExprValue common_lhs = dw_expr_cast(lhs, result.type);
|
|
DW_ExprValue common_rhs = dw_expr_cast(rhs, result.type);
|
|
|
|
switch (result.type) {
|
|
case DW_ExprValueType_Generic: { InvalidPath; } break;
|
|
|
|
case DW_ExprValueType_U8: { InvalidPath; } break;
|
|
case DW_ExprValueType_U16: { InvalidPath; } break;
|
|
case DW_ExprValueType_U32: { InvalidPath; } break;
|
|
case DW_ExprValueType_U64: { InvalidPath; } break;
|
|
case DW_ExprValueType_U128: { InvalidPath; } break;
|
|
case DW_ExprValueType_U256: { InvalidPath; } break;
|
|
case DW_ExprValueType_U512: { InvalidPath; } break;
|
|
|
|
case DW_ExprValueType_Bool: { result.s8 = common_lhs.s8 >> common_rhs.s8; } break;
|
|
case DW_ExprValueType_S8: { result.s8 = common_lhs.s8 >> common_rhs.s8; } break;
|
|
case DW_ExprValueType_S16: { result.s16 = common_lhs.s16 >> common_rhs.s16; } break;
|
|
case DW_ExprValueType_S32: { result.s32 = common_lhs.s32 >> common_rhs.s32; } break;
|
|
case DW_ExprValueType_S64: { result.s64 = common_lhs.s64 >> common_rhs.s64; } break;
|
|
|
|
case DW_ExprValueType_S128:
|
|
case DW_ExprValueType_S256:
|
|
case DW_ExprValueType_S512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_F32: { InvalidPath; } break;
|
|
case DW_ExprValueType_F64: { InvalidPath; } break;
|
|
case DW_ExprValueType_Addr: { result.addr = common_lhs.addr >> common_rhs.addr; } break;
|
|
case DW_ExprValueType_Implicit: { InvalidPath; } break;
|
|
|
|
default: { InvalidPath; } break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
internal DW_ExprValue
|
|
dw_expr_abs(DW_ExprValue value)
|
|
{
|
|
DW_ExprValue result = value;
|
|
|
|
switch (value.type) {
|
|
case DW_ExprValueType_Generic: { InvalidPath; } break;
|
|
|
|
case DW_ExprValueType_U8: {}; break;
|
|
case DW_ExprValueType_U16: {}; break;
|
|
case DW_ExprValueType_U32: {}; break;
|
|
case DW_ExprValueType_U64: {}; break;
|
|
case DW_ExprValueType_U128: {}; break;
|
|
case DW_ExprValueType_U256: {}; break;
|
|
case DW_ExprValueType_U512: {}; break;
|
|
|
|
case DW_ExprValueType_S8: { result.s8 = abs_s64(result.s8); } break;
|
|
case DW_ExprValueType_S16: { result.s16 = abs_s64(result.s16); } break;
|
|
case DW_ExprValueType_S32: { result.s32 = abs_s64(result.s32); } break;
|
|
case DW_ExprValueType_S64: { result.s64 = abs_s64(result.s64); } break;
|
|
case DW_ExprValueType_S128: { NotImplemented; } break;
|
|
case DW_ExprValueType_S256: { NotImplemented; } break;
|
|
case DW_ExprValueType_S512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_F32: { result.f32 = abs_f32(result.f32); } break;
|
|
case DW_ExprValueType_F64: { result.f64 = abs_f64(result.f64); } break;
|
|
|
|
case DW_ExprValueType_Addr: {} break;
|
|
case DW_ExprValueType_Bool: { result.boolean = abs_s64(result.boolean); } break;
|
|
case DW_ExprValueType_Implicit: { InvalidPath; } break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
internal DW_ExprValue
|
|
dw_expr_neg(DW_ExprValue value)
|
|
{
|
|
DW_ExprValue result = value;
|
|
|
|
switch (value.type) {
|
|
case DW_ExprValueType_Generic: { InvalidPath; } break;
|
|
|
|
case DW_ExprValueType_U8: { result.u8 = -result.u8; }; break;
|
|
case DW_ExprValueType_U16: { result.u16 = -result.u16; }; break;
|
|
case DW_ExprValueType_U32: { result.u32 = -result.u32; }; break;
|
|
case DW_ExprValueType_U64: { result.u64 = -result.u64; }; break;
|
|
case DW_ExprValueType_U128: { NotImplemented; }; break;
|
|
case DW_ExprValueType_U256: { NotImplemented; }; break;
|
|
case DW_ExprValueType_U512: { NotImplemented; }; break;
|
|
|
|
case DW_ExprValueType_S8: { result.s8 = -result.s8; } break;
|
|
case DW_ExprValueType_S16: { result.s16 = -result.s16; } break;
|
|
case DW_ExprValueType_S32: { result.s32 = -result.s32; } break;
|
|
case DW_ExprValueType_S64: { result.s64 = -result.s64; } break;
|
|
case DW_ExprValueType_S128: { NotImplemented; } break;
|
|
case DW_ExprValueType_S256: { NotImplemented; } break;
|
|
case DW_ExprValueType_S512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_F32: { result.f32 = -result.f32; } break;
|
|
case DW_ExprValueType_F64: { result.f64 = -result.f64; } break;
|
|
|
|
case DW_ExprValueType_Addr: { result.addr = -result.addr; } break;
|
|
case DW_ExprValueType_Bool: { result.boolean = abs_s64(result.boolean); } break;
|
|
case DW_ExprValueType_Implicit: { InvalidPath; } break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
internal DW_ExprValue
|
|
dw_expr_not(DW_ExprValue value)
|
|
{
|
|
DW_ExprValue result = value;
|
|
|
|
switch (value.type) {
|
|
case DW_ExprValueType_Generic: { InvalidPath; } break;
|
|
|
|
case DW_ExprValueType_U8: { result.u8 = !result.u8; }; break;
|
|
case DW_ExprValueType_U16: { result.u16 = !result.u16; }; break;
|
|
case DW_ExprValueType_U32: { result.u32 = !result.u32; }; break;
|
|
case DW_ExprValueType_U64: { result.u64 = !result.u64; }; break;
|
|
case DW_ExprValueType_U128: { NotImplemented; }; break;
|
|
case DW_ExprValueType_U256: { NotImplemented; }; break;
|
|
case DW_ExprValueType_U512: { NotImplemented; }; break;
|
|
|
|
case DW_ExprValueType_S8: { result.s8 = !result.s8; } break;
|
|
case DW_ExprValueType_S16: { result.s16 = !result.s16; } break;
|
|
case DW_ExprValueType_S32: { result.s32 = !result.s32; } break;
|
|
case DW_ExprValueType_S64: { result.s64 = !result.s64; } break;
|
|
case DW_ExprValueType_S128: { NotImplemented; } break;
|
|
case DW_ExprValueType_S256: { NotImplemented; } break;
|
|
case DW_ExprValueType_S512: { NotImplemented; } break;
|
|
|
|
case DW_ExprValueType_F32: { result.f32 = !result.f32; } break;
|
|
case DW_ExprValueType_F64: { result.f64 = !result.f64; } break;
|
|
|
|
case DW_ExprValueType_Addr: { result.addr = !result.addr; } break;
|
|
case DW_ExprValueType_Bool: { result.boolean = abs_s64(result.boolean); } break;
|
|
case DW_ExprValueType_Implicit: { InvalidPath; } break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
internal String8
|
|
dw_string_from_expr_value(Arena *arena, U64 addr_size, DW_ExprValue v)
|
|
{
|
|
String8 s = {0};
|
|
switch (v.type) {
|
|
case DW_ExprValueType_Generic: { } break;
|
|
case DW_ExprValueType_U8: { s = str8_struct(&v.u8); } break;
|
|
case DW_ExprValueType_U16: { s = str8_struct(&v.u16); } break;
|
|
case DW_ExprValueType_U32: { s = str8_struct(&v.u32); } break;
|
|
case DW_ExprValueType_U64: { s = str8_struct(&v.u64); } break;
|
|
case DW_ExprValueType_U128: { s = str8_struct(&v.u128); } break;
|
|
case DW_ExprValueType_U256: { s = str8_struct(&v.u256); } break;
|
|
case DW_ExprValueType_U512: { s = str8_struct(&v.u512); } break;
|
|
case DW_ExprValueType_S8: { s = str8_struct(&v.s8); } break;
|
|
case DW_ExprValueType_S16: { s = str8_struct(&v.s16); } break;
|
|
case DW_ExprValueType_S32: { s = str8_struct(&v.s32); } break;
|
|
case DW_ExprValueType_S64: { s = str8_struct(&v.s64); } break;
|
|
case DW_ExprValueType_F32: { s = str8_struct(&v.f32); } break;
|
|
case DW_ExprValueType_F64: { s = str8_struct(&v.f64); } break;
|
|
case DW_ExprValueType_Addr: { s = str8((U8 *)&v.addr, addr_size); } break;
|
|
case DW_ExprValueType_Implicit: { s = v.implicit; } break;
|
|
default: { NotImplemented; } break;
|
|
}
|
|
return str8_copy(arena, s);
|
|
}
|
|
|
|
internal DW_ExprValueNode *
|
|
dw_expr_stack_push(Arena *arena, DW_ExprStack *stack, DW_ExprValue value)
|
|
{
|
|
DW_ExprValueNode *n = push_array(arena, DW_ExprValueNode, 1);
|
|
n->v = value;
|
|
SLLStackPush(stack->top, n);
|
|
stack->count += 1;
|
|
return n;
|
|
}
|
|
|
|
internal DW_ExprValueNode *
|
|
dw_expr_stack_push_unsigned(Arena *arena, DW_ExprStack *stack, void *value, U64 value_size)
|
|
{
|
|
DW_ExprValueNode *n = 0;
|
|
switch (value_size) {
|
|
case 0: {} break;
|
|
case 1: { n = dw_expr_stack_push(arena, stack, (DW_ExprValue){ .type = DW_ExprValueType_U8, .u8 = *(U8 *)value }); } break;
|
|
case 2: { n = dw_expr_stack_push(arena, stack, (DW_ExprValue){ .type = DW_ExprValueType_U16, .u16 = *(U16 *)value }); } break;
|
|
case 4: { n = dw_expr_stack_push(arena, stack, (DW_ExprValue){ .type = DW_ExprValueType_U32, .u32 = *(U32 *)value }); } break;
|
|
case 8: { n = dw_expr_stack_push(arena, stack, (DW_ExprValue){ .type = DW_ExprValueType_U64, .u64 = *(U64 *)value }); } break;
|
|
default: { NotImplemented; } break;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
internal DW_ExprValue
|
|
dw_expr_stack_pop(DW_ExprStack *stack)
|
|
{
|
|
DW_ExprValueNode *n = stack->top;
|
|
DW_ExprValue v = n->v;
|
|
SLLStackPop(stack->top);
|
|
return v;
|
|
}
|
|
|
|
internal DW_ExprValue
|
|
dw_expr_stack_peek(DW_ExprStack *stack)
|
|
{
|
|
return stack->top->v;
|
|
}
|
|
|
|
internal DW_ExprValueNode *
|
|
dw_expr_stack_pick(DW_ExprStack *stack, U64 idx)
|
|
{
|
|
DW_ExprValueNode *n = 0;
|
|
if (idx < stack->count) {
|
|
U64 c = idx;
|
|
for (n = stack->top; n != 0 && c > 0; n = n->next, c -= 1);
|
|
}
|
|
return n;
|
|
}
|
|
|
|
internal DW_ExprInst *
|
|
dw_expr_inst_from_delta(DW_ExprInst *inst, S16 delta)
|
|
{
|
|
B32 skip_fwd = inst->operands[0].s16 >= 0;
|
|
DW_ExprInst *i = inst;
|
|
U16 u_delta = abs_s64(inst->operands[0].s16);
|
|
U64 cursor = 0;
|
|
for (i = skip_fwd ? inst : inst->prev; i != 0 && cursor < u_delta; i = skip_fwd ? inst->next : inst->prev) {
|
|
cursor += inst->size;
|
|
}
|
|
if (cursor != u_delta) {
|
|
i = 0;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
internal DW_ExprEvalResult
|
|
dw_eval_expr(Arena *arena, Arch arch, DW_Format format, U64 frame_base, U64 cfa, U64 tls, U64 exec_op_limit, DW_Expr expr, void *reg_block, MachineOp_MemRead *mem_read, void *mem_read_ud, DW_ExprValue *value_out)
|
|
{
|
|
Temp scratch = scratch_begin(&arena, 1);
|
|
|
|
ARCH_Info *arch_info = arch_info_from_arch(arch);
|
|
|
|
DW_ExprEvalResult result = DW_ExprEvalResult_Fail;
|
|
DW_PieceList pieces = {0};
|
|
DW_ExprStack *stack = push_array(scratch.arena, DW_ExprStack, 1);
|
|
U64 exec_op_count = 0;
|
|
|
|
for EachNode(inst, DW_ExprInst, expr.first) {
|
|
again:;
|
|
|
|
exec_op_count += 1;
|
|
if (exec_op_count > exec_op_limit) {
|
|
Assert(0 && "reached opcode exec limit on the expression");
|
|
result = DW_ExprEvalResult_ExecOpLimitReached;
|
|
goto exit;
|
|
}
|
|
|
|
U64 pop_count = dw_pop_count_from_expr_op(inst->opcode);
|
|
if (pop_count > stack->count) {
|
|
Assert(0 && "not enough values on the stack to evaluate the instruction");
|
|
goto exit;
|
|
}
|
|
|
|
switch (inst->opcode) {
|
|
case DW_ExprOp_Nop: {} break;
|
|
|
|
case DW_ExprOp_Lit0: case DW_ExprOp_Lit1: case DW_ExprOp_Lit2:
|
|
case DW_ExprOp_Lit3: case DW_ExprOp_Lit4: case DW_ExprOp_Lit5:
|
|
case DW_ExprOp_Lit6: case DW_ExprOp_Lit7: case DW_ExprOp_Lit8:
|
|
case DW_ExprOp_Lit9: case DW_ExprOp_Lit10: case DW_ExprOp_Lit11:
|
|
case DW_ExprOp_Lit12: case DW_ExprOp_Lit13: case DW_ExprOp_Lit14:
|
|
case DW_ExprOp_Lit15: case DW_ExprOp_Lit16: case DW_ExprOp_Lit17:
|
|
case DW_ExprOp_Lit18: case DW_ExprOp_Lit19: case DW_ExprOp_Lit20:
|
|
case DW_ExprOp_Lit21: case DW_ExprOp_Lit22: case DW_ExprOp_Lit23:
|
|
case DW_ExprOp_Lit24: case DW_ExprOp_Lit25: case DW_ExprOp_Lit26:
|
|
case DW_ExprOp_Lit27: case DW_ExprOp_Lit28: case DW_ExprOp_Lit29:
|
|
case DW_ExprOp_Lit30: case DW_ExprOp_Lit31: {
|
|
dw_expr_stack_push(scratch.arena, stack, (DW_ExprValue){ .type = DW_ExprValueType_U8, .u8 = inst->opcode - DW_ExprOp_Lit0 });
|
|
} break;
|
|
|
|
case DW_ExprOp_Const1U: { dw_expr_stack_push(scratch.arena, stack, (DW_ExprValue){ .type = DW_ExprValueType_U8, .u8 = inst->operands[0].u8 }); } break;
|
|
case DW_ExprOp_Const2U: { dw_expr_stack_push(scratch.arena, stack, (DW_ExprValue){ .type = DW_ExprValueType_U16, .u16 = inst->operands[0].u16 }); } break;
|
|
case DW_ExprOp_Const4U: { dw_expr_stack_push(scratch.arena, stack, (DW_ExprValue){ .type = DW_ExprValueType_U32, .u32 = inst->operands[0].u32 }); } break;
|
|
case DW_ExprOp_Const8U: { dw_expr_stack_push(scratch.arena, stack, (DW_ExprValue){ .type = DW_ExprValueType_U64, .u64 = inst->operands[0].u64 }); } break;
|
|
case DW_ExprOp_Const1S: { dw_expr_stack_push(scratch.arena, stack, (DW_ExprValue){ .type = DW_ExprValueType_S8, .s8 = inst->operands[0].s8 }); } break;
|
|
case DW_ExprOp_Const2S: { dw_expr_stack_push(scratch.arena, stack, (DW_ExprValue){ .type = DW_ExprValueType_S16, .s16 = inst->operands[0].s16 }); } break;
|
|
case DW_ExprOp_Const4S: { dw_expr_stack_push(scratch.arena, stack, (DW_ExprValue){ .type = DW_ExprValueType_S32, .s32 = inst->operands[0].s32 }); } break;
|
|
case DW_ExprOp_Const8S: { dw_expr_stack_push(scratch.arena, stack, (DW_ExprValue){ .type = DW_ExprValueType_S64, .s64 = inst->operands[0].s64 }); } break;
|
|
case DW_ExprOp_ConstU: { dw_expr_stack_push(scratch.arena, stack, (DW_ExprValue){ .type = DW_ExprValueType_U64, .u64 = inst->operands[0].u64 }); } break;
|
|
case DW_ExprOp_ConstS: { dw_expr_stack_push(scratch.arena, stack, (DW_ExprValue){ .type = DW_ExprValueType_S64, .s64 = inst->operands[0].s64 }); } break;
|
|
case DW_ExprOp_Addr: { dw_expr_stack_push(scratch.arena, stack, (DW_ExprValue){ .type = DW_ExprValueType_Addr, .addr = inst->operands[0].u64 }); } break;
|
|
|
|
case DW_ExprOp_Reg0: case DW_ExprOp_Reg1: case DW_ExprOp_Reg2:
|
|
case DW_ExprOp_Reg3: case DW_ExprOp_Reg4: case DW_ExprOp_Reg5:
|
|
case DW_ExprOp_Reg6: case DW_ExprOp_Reg7: case DW_ExprOp_Reg8:
|
|
case DW_ExprOp_Reg9: case DW_ExprOp_Reg10: case DW_ExprOp_Reg11:
|
|
case DW_ExprOp_Reg12: case DW_ExprOp_Reg13: case DW_ExprOp_Reg14:
|
|
case DW_ExprOp_Reg15: case DW_ExprOp_Reg16: case DW_ExprOp_Reg17:
|
|
case DW_ExprOp_Reg18: case DW_ExprOp_Reg19: case DW_ExprOp_Reg20:
|
|
case DW_ExprOp_Reg21: case DW_ExprOp_Reg22: case DW_ExprOp_Reg23:
|
|
case DW_ExprOp_Reg24: case DW_ExprOp_Reg25: case DW_ExprOp_Reg26:
|
|
case DW_ExprOp_Reg27: case DW_ExprOp_Reg28: case DW_ExprOp_Reg29:
|
|
case DW_ExprOp_Reg30: case DW_ExprOp_Reg31:
|
|
{
|
|
DW_Reg reg_dw_id = inst->opcode - DW_ExprOp_Reg0;
|
|
U64 reg_size = dw_reg_size_from_code(arch, reg_dw_id);
|
|
ARCH_RegCode reg_code = arch_reg_code_from_dw(arch, reg_dw_id);
|
|
Rng1U16 reg_rng = arch_info->reg_code_rng_table[reg_code];
|
|
U8 *reg_value = push_array(scratch.arena, U8, reg_size);
|
|
if(!arch_reg_block_read_range(arch_info, reg_block, r1u16(reg_rng.min, reg_rng.min + reg_size), reg_value))
|
|
{
|
|
goto exit;
|
|
}
|
|
dw_expr_stack_push_unsigned(scratch.arena, stack, reg_value, reg_size);
|
|
}break;
|
|
|
|
case DW_ExprOp_BReg0: case DW_ExprOp_BReg1: case DW_ExprOp_BReg2:
|
|
case DW_ExprOp_BReg3: case DW_ExprOp_BReg4: case DW_ExprOp_BReg5:
|
|
case DW_ExprOp_BReg6: case DW_ExprOp_BReg7: case DW_ExprOp_BReg8:
|
|
case DW_ExprOp_BReg9: case DW_ExprOp_BReg10: case DW_ExprOp_BReg11:
|
|
case DW_ExprOp_BReg12: case DW_ExprOp_BReg13: case DW_ExprOp_BReg14:
|
|
case DW_ExprOp_BReg15: case DW_ExprOp_BReg16: case DW_ExprOp_BReg17:
|
|
case DW_ExprOp_BReg18: case DW_ExprOp_BReg19: case DW_ExprOp_BReg20:
|
|
case DW_ExprOp_BReg21: case DW_ExprOp_BReg22: case DW_ExprOp_BReg23:
|
|
case DW_ExprOp_BReg24: case DW_ExprOp_BReg25: case DW_ExprOp_BReg26:
|
|
case DW_ExprOp_BReg27: case DW_ExprOp_BReg28: case DW_ExprOp_BReg29:
|
|
case DW_ExprOp_BReg30: case DW_ExprOp_BReg31:
|
|
{
|
|
DW_Reg reg_dw_id = inst->opcode - DW_ExprOp_BReg0;
|
|
U64 reg_size = dw_reg_size_from_code(arch, reg_dw_id);
|
|
ARCH_RegCode reg_code = arch_reg_code_from_dw(arch, reg_dw_id);
|
|
Rng1U16 reg_rng = arch_info->reg_code_rng_table[reg_code];
|
|
AssertAlways(reg_size <= byte_size_from_arch(arch));
|
|
|
|
U64 reg_value = 0;
|
|
if(!arch_reg_block_read_range(arch_info, reg_block, r1u16(reg_rng.min, reg_rng.min + reg_size), ®_value))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
U64 addr = (U64)((S64)reg_value + inst->operands[0].s64);
|
|
dw_expr_stack_push(scratch.arena, stack, (DW_ExprValue){ .type = DW_ExprValueType_Addr, .addr = addr});
|
|
}break;
|
|
|
|
case DW_ExprOp_RegX:
|
|
{
|
|
DW_Reg reg_dw_id = inst->operands[0].u64;
|
|
U64 reg_size = dw_reg_size_from_code(arch, reg_dw_id);
|
|
U8 *reg_value = push_array(scratch.arena, U8, reg_size);
|
|
ARCH_RegCode reg_code = arch_reg_code_from_dw(arch, reg_dw_id);
|
|
Rng1U16 reg_rng = arch_info->reg_code_rng_table[reg_code];
|
|
if(!arch_reg_block_read_range(arch_info, reg_block, r1u16(reg_rng.min, reg_rng.min + reg_size), reg_value))
|
|
{
|
|
goto exit;
|
|
}
|
|
dw_expr_stack_push_unsigned(scratch.arena, stack, reg_value, reg_size);
|
|
}break;
|
|
|
|
case DW_ExprOp_BRegX:
|
|
{
|
|
DW_Reg reg_dw_id = (DW_Reg)inst->operands[0].u64;
|
|
U64 reg_size = dw_reg_size_from_code(arch, reg_dw_id);
|
|
AssertAlways(reg_size <= byte_size_from_arch(arch));
|
|
ARCH_RegCode reg_code = arch_reg_code_from_dw(arch, reg_dw_id);
|
|
Rng1U16 reg_rng = arch_info->reg_code_rng_table[reg_code];
|
|
|
|
U64 reg_value = 0;
|
|
if(!arch_reg_block_read_range(arch_info, reg_block, r1u16(reg_rng.min, reg_rng.min + reg_size), ®_value))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
U64 addr = (U64)((S64)reg_value + inst->operands[1].s64);
|
|
dw_expr_stack_push(scratch.arena, stack, (DW_ExprValue){ .type = DW_ExprValueType_Addr, .addr = addr});
|
|
}break;
|
|
|
|
case DW_ExprOp_FBReg: {
|
|
U64 addr = frame_base + inst->operands[0].s64;
|
|
dw_expr_stack_push(scratch.arena, stack, (DW_ExprValue){ .type = DW_ExprValueType_Addr, .addr = addr});
|
|
} break;
|
|
|
|
case DW_ExprOp_ImplicitValue: {
|
|
if (inst->operands[0].block.size <= sizeof(U512)) {
|
|
dw_expr_stack_push_unsigned(scratch.arena, stack, inst->operands[0].block.str, inst->operands[0].block.size);
|
|
} else {
|
|
NotImplemented;
|
|
}
|
|
} break;
|
|
|
|
case DW_ExprOp_Piece: {
|
|
B32 is_undefined = stack->count == 0 || (inst->prev && inst->prev->opcode == DW_ExprOp_Piece);
|
|
if (is_undefined) {
|
|
dw_piece_list_push(arena, &pieces, (DW_Piece){ .kind = DW_PieceKind_Undefined, .bit_size = inst->operands[0].u64 * 8 });
|
|
} else {
|
|
DW_ExprValue top = dw_expr_stack_pop(stack);
|
|
|
|
String8 value;
|
|
|
|
// piece is a memory reference
|
|
if (top.type == DW_ExprValueType_Addr) {
|
|
U64 value_size = inst->operands[0].u64;
|
|
U8 *value_buffer = push_array(arena, U8, value_size);
|
|
MachineOpResult read_result = mem_read(top.addr, value_buffer, value_size, mem_read_ud);
|
|
if (read_result != MachineOpResult_Ok) { Assert(0 && "failed to read piece memory referece"); goto exit; }
|
|
}
|
|
// piece is a value
|
|
else {
|
|
value = dw_string_from_expr_value(arena, arch, top);
|
|
}
|
|
|
|
if (inst->operands[0].u64 > value.size) { Assert(0 && "out of bounds size in the piece opcode"); goto exit; }
|
|
dw_piece_list_push(arena, &pieces, (DW_Piece){ .kind = DW_PieceKind_Value, .bit_size = inst->operands[0].u64 * 8, .value = value.str });
|
|
}
|
|
} break;
|
|
|
|
case DW_ExprOp_BitPiece: {
|
|
B32 is_undefined = stack->count == 0 || (inst->prev && inst->prev->opcode == DW_ExprOp_Piece);
|
|
if (is_undefined) {
|
|
dw_piece_list_push(arena, &pieces, (DW_Piece){ .kind = DW_PieceKind_Undefined, .bit_size = inst->operands[0].u64 });
|
|
} else {
|
|
String8 value;
|
|
if (dw_expr_stack_peek(stack).type == DW_ExprValueType_Addr) {
|
|
NotImplemented;
|
|
} else {
|
|
value = dw_string_from_expr_value(arena, arch, dw_expr_stack_pop(stack));
|
|
}
|
|
if (inst->operands[0].u64 > value.size * 8) { Assert(0 && "out of bounds size in piece opcode"); goto exit; }
|
|
dw_piece_list_push(arena, &pieces, (DW_Piece){ .kind = DW_PieceKind_Value, .bit_size = inst->operands[0].u64, .value = value.str });
|
|
}
|
|
} break;
|
|
|
|
case DW_ExprOp_Pick: {
|
|
DW_ExprValueNode *src = dw_expr_stack_pick(stack, inst->operands[0].u8);
|
|
if (src) {
|
|
dw_expr_stack_push(scratch.arena, stack, src->v);
|
|
} else {
|
|
Assert(0 && "out of bounds stack index");
|
|
goto exit;
|
|
}
|
|
} break;
|
|
|
|
case DW_ExprOp_Over: {
|
|
DW_ExprValueNode *src = dw_expr_stack_pick(stack, 1);
|
|
if (src) {
|
|
dw_expr_stack_push(scratch.arena, stack, src->v);
|
|
} else {
|
|
Assert(0 && "out of bounds stack index");
|
|
goto exit;
|
|
}
|
|
} break;
|
|
|
|
case DW_ExprOp_PlusUConst: {
|
|
DW_ExprValue lhs = dw_expr_stack_pop(stack);
|
|
DW_ExprValue rhs = { .type = DW_ExprValueType_U64, .u64 = inst->operands[0].u64 };
|
|
DW_ExprValue sum = dw_expr_add(lhs, rhs);
|
|
dw_expr_stack_push(scratch.arena, stack, sum);
|
|
} break;
|
|
|
|
case DW_ExprOp_Skip: {
|
|
DW_ExprInst *i = dw_expr_inst_from_delta(inst, inst->operands[0].s16);
|
|
|
|
if (i == 0) {
|
|
Assert(0 && "seeking to an invalid offset");
|
|
goto exit;
|
|
}
|
|
|
|
inst = i;
|
|
goto again;
|
|
}
|
|
|
|
case DW_ExprOp_Bra: {
|
|
DW_ExprValue cond = dw_expr_stack_pop(stack);
|
|
|
|
if (cond.type != DW_ExprValueType_S16) {
|
|
Assert(0 && "unexpected value");
|
|
goto exit;
|
|
}
|
|
|
|
DW_ExprInst *i = dw_expr_inst_from_delta(inst, inst->operands[0].s16);
|
|
|
|
if (i == 0) {
|
|
Assert(0 && "seeking to an invalid offset");
|
|
goto exit;
|
|
}
|
|
|
|
inst = i;
|
|
goto again;
|
|
}
|
|
|
|
case DW_ExprOp_Call2:
|
|
case DW_ExprOp_Call4:
|
|
case DW_ExprOp_CallRef: {
|
|
NotImplemented;
|
|
} break;
|
|
|
|
case DW_ExprOp_GNU_Convert:
|
|
case DW_ExprOp_Convert: {
|
|
if (inst->operands[0].u64 == 0) {
|
|
DW_ExprValue value = dw_expr_stack_pop(stack);
|
|
DW_ExprValue new_value = dw_expr_cast(value, DW_ExprValueType_Generic);
|
|
dw_expr_stack_push(scratch.arena, stack, new_value);
|
|
} else {
|
|
NotImplemented;
|
|
}
|
|
} break;
|
|
|
|
case DW_ExprOp_Reinterpret: {
|
|
if (inst->operands[0].u64 == 0) {
|
|
DW_ExprValue value = dw_expr_stack_pop(stack);
|
|
DW_ExprValue new_value = dw_expr_cast(value, DW_ExprValueType_Generic);
|
|
dw_expr_stack_push(scratch.arena, stack, new_value);
|
|
} else {
|
|
NotImplemented;
|
|
}
|
|
} break;
|
|
|
|
case DW_ExprOp_GNU_ParameterRef: { NotImplemented; } break;
|
|
case DW_ExprOp_GNU_DerefType: { NotImplemented; } break;
|
|
case DW_ExprOp_DerefType: { NotImplemented; } break;
|
|
case DW_ExprOp_ConstType: { NotImplemented; } break;
|
|
case DW_ExprOp_GNU_ConstType: { NotImplemented; } break;
|
|
case DW_ExprOp_RegvalType: { NotImplemented; } break;
|
|
|
|
case DW_ExprOp_EntryValue:
|
|
case DW_ExprOp_GNU_EntryValue:
|
|
{
|
|
DW_Expr entry_value_expr = dw_expr_from_data(scratch.arena, format, byte_size_from_arch(arch), inst->operands[0].block);
|
|
DW_ExprValue entry_value;
|
|
result = dw_eval_expr(scratch.arena, arch, format, frame_base, cfa, tls, exec_op_limit, entry_value_expr, reg_block, mem_read, mem_read_ud, &entry_value);
|
|
if (result != DW_ExprEvalResult_Ok) { goto exit; }
|
|
dw_expr_stack_push(scratch.arena, stack, entry_value);
|
|
} break;
|
|
|
|
case DW_ExprOp_Addrx: { NotImplemented; } break;
|
|
|
|
case DW_ExprOp_CallFrameCfa: {
|
|
dw_expr_stack_push(scratch.arena, stack, (DW_ExprValue){ .type = DW_ExprValueType_U64, .u64 = cfa });
|
|
} break;
|
|
|
|
case DW_ExprOp_PushObjectAddress: { NotImplemented; } break;
|
|
|
|
case DW_ExprOp_Plus: { dw_expr_stack_push(scratch.arena, stack, dw_expr_add(dw_expr_stack_pop(stack), dw_expr_stack_pop(stack))); } break;
|
|
case DW_ExprOp_Minus: { dw_expr_stack_push(scratch.arena, stack, dw_expr_minus(dw_expr_stack_pop(stack), dw_expr_stack_pop(stack))); } break;
|
|
case DW_ExprOp_Div: { dw_expr_stack_push(scratch.arena, stack, dw_expr_div(dw_expr_stack_pop(stack), dw_expr_stack_pop(stack))); } break;
|
|
case DW_ExprOp_Mul: { dw_expr_stack_push(scratch.arena, stack, dw_expr_mul(dw_expr_stack_pop(stack), dw_expr_stack_pop(stack))); } break;
|
|
case DW_ExprOp_Mod: { dw_expr_stack_push(scratch.arena, stack, dw_expr_mod(dw_expr_stack_pop(stack), dw_expr_stack_pop(stack))); } break;
|
|
|
|
case DW_ExprOp_Eq: { dw_expr_stack_push(scratch.arena, stack, dw_expr_eq(dw_expr_stack_pop(stack), dw_expr_stack_pop(stack))); } break;
|
|
case DW_ExprOp_Ge: { dw_expr_stack_push(scratch.arena, stack, dw_expr_ge(dw_expr_stack_pop(stack), dw_expr_stack_pop(stack))); } break;
|
|
case DW_ExprOp_Gt: { dw_expr_stack_push(scratch.arena, stack, dw_expr_gt(dw_expr_stack_pop(stack), dw_expr_stack_pop(stack))); } break;
|
|
case DW_ExprOp_Le: { dw_expr_stack_push(scratch.arena, stack, dw_expr_le(dw_expr_stack_pop(stack), dw_expr_stack_pop(stack))); } break;
|
|
case DW_ExprOp_Lt: { dw_expr_stack_push(scratch.arena, stack, dw_expr_lt(dw_expr_stack_pop(stack), dw_expr_stack_pop(stack))); } break;
|
|
case DW_ExprOp_Ne: { dw_expr_stack_push(scratch.arena, stack, dw_expr_ne(dw_expr_stack_pop(stack), dw_expr_stack_pop(stack))); } break;
|
|
|
|
case DW_ExprOp_Xor: { dw_expr_stack_push(scratch.arena, stack, dw_expr_xor(dw_expr_stack_pop(stack), dw_expr_stack_pop(stack))); } break;
|
|
case DW_ExprOp_And: { dw_expr_stack_push(scratch.arena, stack, dw_expr_and(dw_expr_stack_pop(stack), dw_expr_stack_pop(stack))); } break;
|
|
case DW_ExprOp_Or: { dw_expr_stack_push(scratch.arena, stack, dw_expr_or(dw_expr_stack_pop(stack), dw_expr_stack_pop(stack))); } break;
|
|
case DW_ExprOp_Shl: { dw_expr_stack_push(scratch.arena, stack, dw_expr_shl(dw_expr_stack_pop(stack), dw_expr_stack_pop(stack))); } break;
|
|
case DW_ExprOp_Shr: { dw_expr_stack_push(scratch.arena, stack, dw_expr_shr(dw_expr_stack_pop(stack), dw_expr_stack_pop(stack))); } break;
|
|
case DW_ExprOp_Shra: { dw_expr_stack_push(scratch.arena, stack, dw_expr_shra(dw_expr_stack_pop(stack), dw_expr_stack_pop(stack))); } break;
|
|
|
|
case DW_ExprOp_Abs: { dw_expr_stack_push(scratch.arena, stack, dw_expr_abs(dw_expr_stack_pop(stack))); } break;
|
|
case DW_ExprOp_Neg: { dw_expr_stack_push(scratch.arena, stack, dw_expr_neg(dw_expr_stack_pop(stack))); } break;
|
|
case DW_ExprOp_Not: { dw_expr_stack_push(scratch.arena, stack, dw_expr_not(dw_expr_stack_pop(stack))); } break;
|
|
|
|
case DW_ExprOp_Dup: {
|
|
dw_expr_stack_push(scratch.arena, stack, dw_expr_stack_peek(stack));
|
|
} break;
|
|
|
|
case DW_ExprOp_Rot: {
|
|
DW_ExprValue first = dw_expr_stack_pop(stack);
|
|
DW_ExprValue second = dw_expr_stack_pop(stack);
|
|
DW_ExprValue third = dw_expr_stack_pop(stack);
|
|
dw_expr_stack_push(scratch.arena, stack, first); // -> third
|
|
dw_expr_stack_push(scratch.arena, stack, third); // -> second
|
|
dw_expr_stack_push(scratch.arena, stack, second); // -> first
|
|
} break;
|
|
|
|
case DW_ExprOp_Swap: {
|
|
DW_ExprValue first = dw_expr_stack_pop(stack);
|
|
DW_ExprValue second = dw_expr_stack_pop(stack);
|
|
dw_expr_stack_push(scratch.arena, stack, first); // -> second
|
|
dw_expr_stack_push(scratch.arena, stack, second); // -> first
|
|
} break;
|
|
|
|
case DW_ExprOp_Drop: {
|
|
dw_expr_stack_pop(stack);
|
|
} break;
|
|
|
|
case DW_ExprOp_Deref: {
|
|
DW_ExprValue value = dw_expr_stack_pop(stack);
|
|
|
|
// expression must be of an integral type
|
|
if (!DW_ExprValueType_IsInt(value.type)) { goto exit; }
|
|
|
|
// treat value as an address
|
|
DW_ExprValue addr = dw_expr_cast(value, DW_ExprValueType_Addr);
|
|
|
|
// read pointer size from the address
|
|
U64 addr_size = byte_size_from_arch(arch);
|
|
U8 *generic_value = push_array(scratch.arena, U8, addr_size);
|
|
MachineOpResult read_result = mem_read(addr.addr, generic_value, addr_size, mem_read_ud);
|
|
if (read_result != MachineOpResult_Ok) { goto exit; }
|
|
|
|
// push generic data
|
|
dw_expr_stack_push(scratch.arena, stack, (DW_ExprValue){ .type = DW_ExprValueType_Generic, .generic = str8(generic_value, addr_size) });
|
|
} break;
|
|
|
|
case DW_ExprOp_StackValue: {
|
|
stack->top->v.type = dw_expr_unsigned_value_type_from_bit_size(bit_size_from_arch(arch));
|
|
} break;
|
|
|
|
case DW_ExprOp_GNU_PushTlsAddress:
|
|
case DW_ExprOp_FormTlsAddress: {
|
|
DW_ExprValue tls_off = dw_expr_stack_pop(stack);
|
|
DW_ExprValue tls_base = { .type = DW_ExprValueType_Addr, .addr = tls };
|
|
DW_ExprValue tls_addr = dw_expr_add(tls_base, tls_off);
|
|
dw_expr_stack_push(scratch.arena, stack, tls_addr);
|
|
} break;
|
|
}
|
|
}
|
|
|
|
// composite value
|
|
if (pieces.count > 0) {
|
|
#if 0
|
|
U64 total_bit_size = 0;
|
|
for EachNode (n, DW_PieceNode, pieces.first) {
|
|
total_bit_size += n->v.bit_size;
|
|
}
|
|
|
|
U64 value_size = CeilIntegerDiv(total_bit_size, 8);
|
|
U8 *value = push_array(arena, U8, value_size);
|
|
Rng1U64 *ranges = push_array(arena, Rng1U64, pieces.count);
|
|
U64 *offsets = push_array(arena, U64, pieces.count);
|
|
U64 value_idx = 0;
|
|
U64 value_cursor = 0;
|
|
U64 piece_cursor = 0;
|
|
for EachNode(n, DW_PieceNode, pieces.first) {
|
|
if (n->v.kind == DW_PieceKind_Value) {
|
|
ranges[value_idx] = r1u64(piece_cursor, piece_cursor + n->v.bit_size);
|
|
offsets[value_idx] = value_cursor;
|
|
for (U64 i = 0; i < n->v.bit_size; i += 8) {
|
|
U64 to_copy = Min(8, n->v.bit_size - i);
|
|
if (value_cursor % 8 == 0) {
|
|
value[value_cursor / 8] = n->v.value[i];
|
|
} else {
|
|
value[value_cursor / 8] |= n->v.value[i] << (value_cursor % 8);
|
|
value[AlignPow2(value_cursor / 8, 8)] |= n->v.value[i] >> (value_cursor % 8);
|
|
}
|
|
value_cursor += to_copy;
|
|
}
|
|
value_idx += 1;
|
|
}
|
|
piece_cursor += n->v.bit_size;
|
|
}
|
|
|
|
value_out->type = DW_ExprValueType_Generic;
|
|
value_out->ranges = (Rng1U64Array){ .count = pieces.count, .v = ranges };
|
|
value_out->offsets = offsets;
|
|
value_out->generic = str8(value, value_size);
|
|
#else
|
|
NotImplemented;
|
|
#endif
|
|
}
|
|
// scalar
|
|
else {
|
|
if (stack->top) {
|
|
*value_out = stack->top->v;
|
|
if (value_out->type == DW_ExprValueType_Generic) {
|
|
value_out->generic = push_str8_copy(arena, value_out->generic);
|
|
}
|
|
|
|
Rng1U64 *range = push_array(arena, Rng1U64, 1);
|
|
*range = r1u64(0, max_U64);
|
|
value_out->ranges = (Rng1U64Array){ .count = 1, .v = range };
|
|
value_out->offsets = push_array(arena, U64, 1);
|
|
} else {
|
|
MemoryZeroStruct(value_out);
|
|
}
|
|
}
|
|
|
|
result = DW_ExprEvalResult_Ok;
|
|
exit:;
|
|
scratch_end(scratch);
|
|
return result;
|
|
}
|