Files
raddebugger/obsolete/dwarf/dwarf_expr_old.c
T

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), &reg_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), &reg_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;
}