Phasor 3.3.0
Stack VM based Programming Language
Loading...
Searching...
No Matches
BytecodeDeserializer.cpp
Go to the documentation of this file.
2#include <cstring>
3#include <stdexcept>
4#include <filesystem>
5#include <phsint.hpp>
6#include "metadata.h"
7
8// Section IDs — must match BytecodeSerializer.cpp
14
16static bool crc32_table_initialized = false;
17
19{
20 for (Phasor::u32 i = 0; i < 256; i++)
21 {
22 Phasor::u32 crc = i;
23 for (int j = 0; j < 8; j++)
24 {
25 if ((crc & 1) != 0u)
26 crc = (crc >> 1) ^ 0xEDB88320;
27 else
28 crc >>= 1;
29 }
30 crc32_table[i] = crc;
31 }
33}
34
35namespace Phasor
36{
37
39{
42
43 u32 crc = 0xFFFFFFFF;
44 for (size_t i = 0; i < size; i++)
45 crc = (crc >> 8) ^ crc32_table[(crc ^ data[i]) & 0xFF];
46 return crc ^ 0xFFFFFFFF;
47}
48
49// ---------------------------------------------------------------------------
50// Primitive readers
51// ---------------------------------------------------------------------------
52
54{
55 if (position >= dataSize)
56 throw std::runtime_error("Unexpected end of bytecode data");
57 return _data[position++];
58}
59
61{
62 u16 value = 0;
63 value |= static_cast<u16>(readUInt8());
64 value |= static_cast<u16>(readUInt8()) << 8;
65 return value;
66}
67
69{
70 u32 value = 0;
71 value |= static_cast<u32>(readUInt8());
72 value |= static_cast<u32>(readUInt8()) << 8;
73 value |= static_cast<u32>(readUInt8()) << 16;
74 value |= static_cast<u32>(readUInt8()) << 24;
75 return value;
76}
77
79{
80 return static_cast<i32>(readUInt32());
81}
82
84{
85 i64 value = 0;
86 for (int i = 0; i < 8; i++)
87 value |= static_cast<i64>(readUInt8()) << (i * 8);
88 return value;
89}
90
92{
93 u64 bits = 0;
94 for (int i = 0; i < 8; i++)
95 bits |= static_cast<u64>(readUInt8()) << (i * 8);
96 f64 value;
97 std::memcpy(&value, &bits, sizeof(f64));
98 return value;
99}
100
102{
103 u16 length = readUInt16();
104 std::string str;
105 str.reserve(length);
106 for (u16 i = 0; i < length; i++)
107 str.push_back(static_cast<char>(readUInt8()));
108 return str;
109}
110
111// ---------------------------------------------------------------------------
112// Recursive value reader — mirrors BytecodeSerializer::writeValue exactly.
113// ---------------------------------------------------------------------------
115{
116 u8 typeTag = readUInt8();
117
118 switch (typeTag)
119 {
120 case 0: // Null
121 return Value{};
122
123 case 1: // Bool
124 return Value{readUInt8() != 0};
125
126 case 2: // Int
127 return Value{readInt64()};
128
129 case 3: // Float
130 return Value{readDouble()};
131
132 case 4: // String
133 return Value{readString()};
134
135 case 5: // Struct
136 {
137 std::string typeName = readString();
138 u32 fieldCount = readUInt32();
139
140 Value structVal = Value::createStruct(PhsString(typeName));
141 for (u32 i = 0; i < fieldCount; ++i)
142 {
143 std::string fieldName = readString();
144 Value fieldVal = readValue(); // recurse
145 structVal.setField(PhsString(fieldName), std::move(fieldVal));
146 }
147 return structVal;
148 }
149
150 case 6: // Array
151 {
152 u32 elementCount = readUInt32();
153 std::vector<Value> elements;
154 elements.reserve(elementCount);
155 for (u32 i = 0; i < elementCount; ++i)
156 elements.push_back(readValue()); // recurse
157 return Value::createArray(std::move(elements));
158 }
159
160 default:
161 throw std::runtime_error("BytecodeDeserializer::readValue: unknown type tag " +
162 std::to_string(typeTag));
163 }
164}
165
166// ---------------------------------------------------------------------------
167// Section readers
168// ---------------------------------------------------------------------------
169
171{
172 u32 magic = readUInt32();
173 if (magic != MAGIC_NUMBER)
174 throw std::runtime_error("Invalid bytecode file: incorrect magic number");
175
176 u32 version = readUInt32();
177 if (version != VERSION)
178 throw std::runtime_error("Incompatible bytecode version");
179
180 u32 flags = readUInt32(); // Reserved
181 (void)flags;
182
183 checksum = readUInt32();
184}
185
187{
188 u8 sectionId = readUInt8();
189 if (sectionId != SECTION_CONSTANTS)
190 throw std::runtime_error("Expected constant pool section");
191
192 u32 count = readUInt32();
193 bytecode.constants.reserve(count);
194 for (u32 i = 0; i < count; i++)
195 bytecode.constants.push_back(readValue());
196}
197
199{
200 u8 sectionId = readUInt8();
201 if (sectionId != SECTION_VARIABLES)
202 throw std::runtime_error("Expected variable mapping section");
203
204 u32 count = readUInt32();
205 bytecode.nextVarIndex = readInt32();
206 for (u32 i = 0; i < count; i++)
207 {
208 std::string name = readString();
209 i32 index = readInt32();
210 bytecode.variables[name] = index;
211 }
212}
213
215{
216 u8 sectionId = readUInt8();
217 if (sectionId != SECTION_INSTRUCTIONS)
218 throw std::runtime_error("Expected instructions section");
219
220 u32 count = readUInt32();
221 bytecode.instructions.reserve(count);
222 for (u32 i = 0; i < count; i++)
223 {
224 u8 opcode = readUInt8();
225 i32 op1 = readInt32();
226 i32 op2 = readInt32();
227 i32 op3 = readInt32();
228 bytecode.instructions.emplace_back(static_cast<OpCode>(opcode), op1, op2, op3);
229 }
230}
231
233{
234 u8 sectionId = readUInt8();
235 if (sectionId != SECTION_FUNCTIONS)
236 throw std::runtime_error("Expected function entries section");
237
238 u32 count = readUInt32();
239 for (u32 i = 0; i < count; i++)
240 {
241 std::string name = readString();
242 i32 address = readInt32();
243 bytecode.functionEntries[name] = address;
244 }
245}
246
253{
254 u8 sectionId = readUInt8();
255 if (sectionId != SECTION_STRUCTS)
256 throw std::runtime_error("Expected struct definitions section");
257
258 u32 structCount = readUInt32();
259 bytecode.structs.reserve(structCount);
260
261 for (u32 i = 0; i < structCount; i++)
262 {
263 StructInfo info;
264 info.name = readString();
265 info.firstConstIndex = readInt32();
266 info.fieldCount = readInt32();
267
268 info.fieldNames.reserve(static_cast<size_t>(info.fieldCount));
269 for (int f = 0; f < info.fieldCount; f++)
270 info.fieldNames.push_back(readString());
271
272 int index = static_cast<int>(bytecode.structs.size());
273 bytecode.structs.push_back(std::move(info));
274 bytecode.structEntries[bytecode.structs.back().name] = index;
275 }
276}
277
278// ---------------------------------------------------------------------------
279// Top-level deserialize / loadFromFile
280// ---------------------------------------------------------------------------
281
282Bytecode BytecodeDeserializer::deserialize(const std::vector<u8> &buffer)
283{
284 _data = buffer.data();
285 dataSize = buffer.size();
286 position = 0;
287
288 Bytecode bytecode;
289
290 u32 expectedChecksum;
291 readHeader(expectedChecksum);
292
293 size_t dataStart = position;
294 u32 actualChecksum = calculateCRC32(_data + dataStart, dataSize - dataStart);
295 if (actualChecksum != expectedChecksum)
296 throw std::runtime_error("Bytecode file corrupted: checksum mismatch");
297
298 // Sections must be read in the same order they were written.
299 readConstantPool(bytecode);
300 readVariableMapping(bytecode);
301 readFunctionEntries(bytecode);
302 readStructSection(bytecode);
303 readInstructions(bytecode);
304
305 return bytecode;
306}
307
308Bytecode BytecodeDeserializer::loadFromFile(const std::filesystem::path &filename)
309{
310 std::ifstream file(filename, std::ios::binary | std::ios::ate);
311 if (!file.is_open())
312 throw std::runtime_error("Failed to open bytecode file: " + filename.string());
313
314 std::streamsize size = file.tellg();
315 file.seekg(0, std::ios::beg);
316
317 std::vector<u8> fileBuffer(size);
318 if (!file.read(reinterpret_cast<char *>(fileBuffer.data()), size))
319 throw std::runtime_error("Failed to read bytecode file: " + filename.string());
320
321 return deserialize(fileBuffer);
322}
323
324} // namespace Phasor
const Phasor::u8 SECTION_FUNCTIONS
void init_crc32_table_deserializer()
const Phasor::u8 SECTION_VARIABLES
const Phasor::u8 SECTION_STRUCTS
const Phasor::u8 SECTION_CONSTANTS
const Phasor::u8 SECTION_INSTRUCTIONS
static Phasor::u32 crc32_table[256]
static bool crc32_table_initialized
void readInstructions(Bytecode &bytecode)
Helper method to read Instructions Table.
i64 readInt64()
Helper method to read Int64.
void readConstantPool(Bytecode &bytecode)
Helper method to read Constants Table.
Value readValue()
Read a single Value (recursive — handles nested structs/arrays).
Bytecode deserialize(const std::vector< u8 > &data)
Deserialize bytecode from binary buffer.
Bytecode loadFromFile(const std::filesystem::path &filename)
Load bytecode from .phsb file.
void readFunctionEntries(Bytecode &bytecode)
Helper method to read Function Entries.
u16 readUInt16()
Helper method to read UInt16.
u32 readUInt32()
Helper method to read UInt32.
static u32 calculateCRC32(const u8 *data, size_t size)
Calculate CRC32 checksum.
void readStructSection(Bytecode &bytecode)
Helper method to read Struct Section.
u8 readUInt8()
Helper method to read UInt8.
void readVariableMapping(Bytecode &bytecode)
Helper method to read Variable Table.
f64 readDouble()
Helper method to read Double.
void readHeader(u32 &checksum)
Helper method to read Header.
i32 readInt32()
Helper method to read Int32.
std::string readString()
Helper method to read String.
A value in the Phasor VM.
Definition Value.hpp:59
static Value createStruct(const PhsString &name)
Definition Value.hpp:567
void setField(const PhsString &name, Value value)
Definition Value.hpp:592
static Value createArray(std::vector< Value > elements={})
Definition Value.hpp:572
const uint32_t VERSION
Version number.
Definition metadata.h:22
#define MAGIC_NUMBER
Magic number (little endian).
Definition metadata.h:15
The Phasor Programming Language and Runtime.
Definition AST.hpp:13
int64_t i64
Definition phsint.hpp:16
uint8_t u8
Definition phsint.hpp:9
double f64
Definition phsint.hpp:7
uint64_t u64
Definition phsint.hpp:12
int32_t i32
Definition phsint.hpp:15
OpCode
Definition ISA.hpp:12
uint16_t u16
Definition phsint.hpp:10
uint32_t u32
Definition phsint.hpp:11
Complete bytecode structure.
Definition CodeGen.hpp:50
std::unordered_map< std::string, int > variables
Variable name -> index mapping.
Definition CodeGen.hpp:53
std::vector< Instruction > instructions
List of instructions.
Definition CodeGen.hpp:51
std::unordered_map< std::string, int > functionEntries
Function name -> instruction index mapping.
Definition CodeGen.hpp:54
int nextVarIndex
Next available variable index.
Definition CodeGen.hpp:56
std::vector< Value > constants
Constant pool.
Definition CodeGen.hpp:52
std::vector< StructInfo > structs
List of struct descriptors.
Definition CodeGen.hpp:59
std::unordered_map< std::string, int > structEntries
Struct name -> index in structs.
Definition CodeGen.hpp:60
Struct metadata stored alongside bytecode (struct section).
Definition CodeGen.hpp:41
int firstConstIndex
Index into constants for the first default value.
Definition CodeGen.hpp:43
std::vector< std::string > fieldNames
Field names in declaration order.
Definition CodeGen.hpp:45
int fieldCount
Number of fields in this struct.
Definition CodeGen.hpp:44
std::string name
Struct name.
Definition CodeGen.hpp:42