summaryrefslogtreecommitdiffstats
path: root/contrib/restricted/wavm/Include/WAVM/IR/Value.h
blob: 98790bde26ac9ec8eaa08b456bad0081d1b781be (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#pragma once

#include <string.h>
#include "WAVM/IR/Types.h"
#include "WAVM/Inline/BasicTypes.h"

namespace WAVM { namespace Runtime {
	struct Object;
	struct Function;
}}

namespace WAVM { namespace IR {
	// A runtime value of any type.
	struct UntaggedValue
	{
		union
		{
			I32 i32;
			U32 u32;
			I64 i64;
			U64 u64;
			F32 f32;
			F64 f64;
			V128 v128;
			U8 bytes[16];
			Runtime::Object* object;
			Runtime::Function* function;
		};

		UntaggedValue(I32 inI32) { i32 = inI32; }
		UntaggedValue(I64 inI64) { i64 = inI64; }
		UntaggedValue(U32 inU32) { u32 = inU32; }
		UntaggedValue(U64 inU64) { u64 = inU64; }
		UntaggedValue(F32 inF32) { f32 = inF32; }
		UntaggedValue(F64 inF64) { f64 = inF64; }
		UntaggedValue(V128 inV128) { v128 = inV128; }
		UntaggedValue(Runtime::Object* inObject) { object = inObject; }
		UntaggedValue(Runtime::Function* inFunction) { function = inFunction; }
		UntaggedValue() { memset(bytes, 0, sizeof(bytes)); }
	};

	// A boxed value: may hold any value that can be passed to a function invoked through the
	// runtime.
	struct Value : UntaggedValue
	{
		ValueType type;

		Value(I32 inI32) : UntaggedValue(inI32), type(ValueType::i32) {}
		Value(I64 inI64) : UntaggedValue(inI64), type(ValueType::i64) {}
		Value(U32 inU32) : UntaggedValue(inU32), type(ValueType::i32) {}
		Value(U64 inU64) : UntaggedValue(inU64), type(ValueType::i64) {}
		Value(F32 inF32) : UntaggedValue(inF32), type(ValueType::f32) {}
		Value(F64 inF64) : UntaggedValue(inF64), type(ValueType::f64) {}
		Value(const V128& inV128) : UntaggedValue(inV128), type(ValueType::v128) {}
		Value(Runtime::Object* inObject) : UntaggedValue(inObject), type(ValueType::externref) {}
		Value(Runtime::Function* inFunction) : UntaggedValue(inFunction), type(ValueType::funcref)
		{
		}
		Value(ValueType inType, UntaggedValue inValue) : UntaggedValue(inValue), type(inType) {}
		Value() : type(ValueType::none) {}

		friend std::string asString(const Value& value)
		{
			switch(value.type)
			{
			case ValueType::i32: return "i32.const " + asString(value.i32);
			case ValueType::i64: return "i64.const " + asString(value.i64);
			case ValueType::f32: return "f32.const " + asString(value.f32);
			case ValueType::f64: return "f64.const " + asString(value.f64);
			case ValueType::v128: return "v128.const " + asString(value.v128);
			case ValueType::externref:
			case ValueType::funcref: {
				// buffer needs 29 characters:
				// (externref|funcref) 0xHHHHHHHHHHHHHHHH\0
				char buffer[29];
				snprintf(buffer,
						 sizeof(buffer),
						 "%s 0x%.16" WAVM_PRIxPTR,
						 value.type == ValueType::externref ? "externref" : "funcref",
						 reinterpret_cast<Uptr>(value.object));
				return std::string(buffer);
			}

			case ValueType::none:
			case ValueType::any:
			default: WAVM_UNREACHABLE();
			}
		}

		friend bool operator==(const Value& left, const Value& right)
		{
			if(left.type != right.type)
			{
				return isReferenceType(left.type) && isReferenceType(right.type)
					   && left.object == right.object;
			}
			switch(left.type)
			{
			case ValueType::none: return true;
			case ValueType::i32:
			case ValueType::f32: return left.i32 == right.i32;
			case ValueType::i64:
			case ValueType::f64: return left.i64 == right.i64;
			case ValueType::v128:
				return left.v128.u64x2[0] == right.v128.u64x2[0]
					   && left.v128.u64x2[1] == right.v128.u64x2[1];
			case ValueType::externref:
			case ValueType::funcref: return left.object == right.object;
			case ValueType::any:
			default: WAVM_UNREACHABLE();
			};
		}

		friend bool operator!=(const Value& left, const Value& right) { return !(left == right); }
	};

	inline std::string asString(const std::vector<Value>& values)
	{
		std::string result = "(";
		for(Uptr elementIndex = 0; elementIndex < values.size(); ++elementIndex)
		{
			if(elementIndex != 0) { result += ", "; }
			result += asString(values[elementIndex]);
		}
		result += ")";
		return result;
	}
}}