Phasor 2.2.0
Stack VM based Programming Language
Loading...
Searching...
No Matches
BytecodeSerializer.cpp
Go to the documentation of this file.
2#include <cstring>
3#include <stdexcept>
4#include <filesystem>
5#include <fstream>
6#include "metadata.h"
7
8#if defined(_MSC_VER)
9#define COMPILE_MESSAGE(msg) __pragma(message(msg))
10#elif defined(__GNUC__) || defined(__clang__)
11#define DO_PRAGMA(x) _Pragma(#x)
12#define COMPILE_MESSAGE(msg) DO_PRAGMA(message msg)
13#else
14#define COMPILE_MESSAGE(msg)
15#endif
16#define STR2(x) #x
17#define STR(x) STR2(x)
18
19// Section IDs
20const uint8_t SECTION_CONSTANTS = 0x01; //< Constants Section
21const uint8_t SECTION_VARIABLES = 0x02; //< Variables Section
22const uint8_t SECTION_INSTRUCTIONS = 0x03; //< Instructions Section
23const uint8_t SECTION_FUNCTIONS = 0x04; //< Functions Section
24
25static uint32_t crc32_table[256]; //< CRC32 lookup table
26static bool crc32_table_initialized = false;
27
30{
31 for (uint32_t i = 0; i < 256; i++)
32 {
33 uint32_t crc = i;
34 for (int j = 0; j < 8; j++)
35 {
36 if (crc & 1)
37 {
38 crc = (crc >> 1) ^ 0xEDB88320;
39 }
40 else
41 {
42 crc >>= 1;
43 }
44 }
45 crc32_table[i] = crc;
46 }
48}
49
50namespace Phasor
51{
52
53uint32_t BytecodeSerializer::calculateCRC32(const std::vector<uint8_t> &data)
54{
56 {
58 }
59
60 uint32_t crc = 0xFFFFFFFF;
61 for (uint8_t byte : data)
62 {
63 crc = (crc >> 8) ^ crc32_table[(crc ^ byte) & 0xFF];
64 }
65 return crc ^ 0xFFFFFFFF;
66}
67
69{
70 buffer.push_back(value);
71}
72
74{
75 buffer.push_back(static_cast<uint8_t>(value & 0xFF));
76 buffer.push_back(static_cast<uint8_t>((value >> 8) & 0xFF));
77}
78
80{
81 buffer.push_back(static_cast<uint8_t>(value & 0xFF));
82 buffer.push_back(static_cast<uint8_t>((value >> 8) & 0xFF));
83 buffer.push_back(static_cast<uint8_t>((value >> 16) & 0xFF));
84 buffer.push_back(static_cast<uint8_t>((value >> 24) & 0xFF));
85}
86
88{
89 writeUInt32(static_cast<uint32_t>(value));
90}
91
93{
94 for (int i = 0; i < 8; i++)
95 {
96 buffer.push_back(static_cast<uint8_t>((value >> (i * 8)) & 0xFF));
97 }
98}
99
101{
102 uint64_t bits;
103 std::memcpy(&bits, &value, sizeof(double));
104 for (int i = 0; i < 8; i++)
105 {
106 buffer.push_back(static_cast<uint8_t>((bits >> (i * 8)) & 0xFF));
107 }
108}
109
110void BytecodeSerializer::writeString(const std::string &str)
111{
112 writeUInt16(static_cast<uint16_t>(str.length()));
113 for (char c : str)
114 {
115 buffer.push_back(static_cast<uint8_t>(c));
116 }
117}
118
119void BytecodeSerializer::writeHeader(uint32_t dataChecksum)
120{
123 writeUInt32(0); // Flags (reserved)
124 writeUInt32(dataChecksum);
125}
126
127void BytecodeSerializer::writeConstantPool(const std::vector<Value> &constants)
128{
130 writeUInt32(static_cast<uint32_t>(constants.size()));
131
132 for (const auto &constant : constants)
133 {
134 ValueType type = constant.getType();
135
136 // Write type tag
137 switch (type)
138 {
139 case ValueType::Null:
140 writeUInt8(0);
141 break;
142 case ValueType::Bool:
143 writeUInt8(1);
144 writeUInt8(constant.asBool() ? 1 : 0);
145 break;
146 case ValueType::Int:
147 writeUInt8(2);
148 writeInt64(constant.asInt());
149 break;
150 case ValueType::Float:
151 writeUInt8(3);
152 writeDouble(constant.asFloat());
153 break;
155 writeUInt8(4);
156 writeString(constant.asString());
157 break;
159COMPILE_MESSAGE("Warning: PHS_01 Structs have not been implemented! Line " STR(__LINE__))
160 throw std::runtime_error("Structs have not been implemented!");
161 break;
162 case ValueType::Array:
163COMPILE_MESSAGE("Warning: PHS_02 Arrays have not been implemented! Line " STR(__LINE__))
164 throw std::runtime_error("Arrays have not been implemented!");
165 break;
166 }
167
168 }
169}
170
171void BytecodeSerializer::writeVariableMapping(const std::map<std::string, int> &variables, int nextVarIndex)
172{
174 writeUInt32(static_cast<uint32_t>(variables.size()));
175 writeInt32(nextVarIndex);
176
177 for (const auto &[name, index] : variables)
178 {
179 writeString(name);
180 writeInt32(index);
181 }
182}
183
184void BytecodeSerializer::writeInstructions(const std::vector<Instruction> &instructions)
185{
187 writeUInt32(static_cast<uint32_t>(instructions.size()));
188
189 for (const auto &instr : instructions)
190 {
191 writeUInt8(static_cast<uint8_t>(instr.op));
192 writeInt32(instr.operand1);
193 writeInt32(instr.operand2);
194 writeInt32(instr.operand3);
195 writeInt32(instr.operand4);
196 writeInt32(instr.operand5);
197 }
198}
199
200void BytecodeSerializer::writeFunctionEntries(const std::map<std::string, int> &functionEntries)
201{
203 writeUInt32(static_cast<uint32_t>(functionEntries.size()));
204
205 for (const auto &[name, address] : functionEntries)
206 {
207 writeString(name);
208 writeInt32(address);
209 }
210}
211
212std::vector<uint8_t> BytecodeSerializer::serialize(const Bytecode &bytecode)
213{
214 buffer.clear();
215
216 for (int i = 0; i < 16; i++)
217 {
218 buffer.push_back(0);
219 }
220
221 // Write all sections
222 size_t dataStartPos = buffer.size();
224 writeVariableMapping(bytecode.variables, bytecode.nextVarIndex);
227
228 // Calculate checksum of data (everything after header)
229 std::vector<uint8_t> dataSection(buffer.begin() + dataStartPos, buffer.end());
230 uint32_t checksum = calculateCRC32(dataSection);
231
232 // Write header at the beginning
233 std::vector<uint8_t> tempBuffer = buffer;
234 buffer.clear();
235 writeHeader(checksum);
236
237 // Append the data sections
238 buffer.insert(buffer.end(), tempBuffer.begin() + 16, tempBuffer.end());
239
240 return buffer;
241}
242
243bool BytecodeSerializer::saveToFile(const Bytecode &bytecode, const std::filesystem::path &filename)
244{
245 try
246 {
247 std::vector<uint8_t> data = serialize(bytecode);
248
249 std::ofstream file(filename, std::ios::binary);
250 if (!file.is_open())
251 {
252 return false;
253 }
254
255 file.write(reinterpret_cast<const char *>(data.data()), data.size());
256 file.close();
257
258 return true;
259 }
260 catch (const std::exception &)
261 {
262 return false;
263 }
264}
265} // namespace Phasor
const uint8_t SECTION_CONSTANTS
const uint8_t SECTION_VARIABLES
const uint8_t SECTION_FUNCTIONS
const uint8_t SECTION_INSTRUCTIONS
static uint32_t crc32_table[256]
static bool crc32_table_initialized
#define COMPILE_MESSAGE(msg)
#define STR(x)
void init_crc32_table()
Init CRC32 Table.
void writeUInt16(uint16_t value)
Helper method to write UInt16.
void writeInstructions(const std::vector< Instruction > &instructions)
Helper method to write Instruction Table.
void writeString(const std::string &str)
Helper method to write String.
void writeInt64(int64_t value)
Helper method to write Int64.
void writeFunctionEntries(const std::map< std::string, int > &functionEntries)
Helper method to write Function Table.
void writeUInt8(uint8_t value)
Helper method to write UInt8.
bool saveToFile(const Bytecode &bytecode, const std::filesystem::path &filename)
Save bytecode to .phsb file.
std::vector< uint8_t > buffer
void writeInt32(int32_t value)
Helper method to write Int32.
uint32_t calculateCRC32(const std::vector< uint8_t > &data)
Calculate CRC32 checksum.
std::vector< uint8_t > serialize(const Bytecode &bytecode)
Serialize bytecode to binary buffer.
void writeHeader(uint32_t dataChecksum)
Section writers.
void writeConstantPool(const std::vector< Value > &constants)
Helper method to write Constants Table.
void writeUInt32(uint32_t value)
Helper method to write UInt32.
void writeDouble(double value)
Helper method to write Double.
void writeVariableMapping(const std::map< std::string, int > &variables, int nextVarIndex)
Helper method to write Variable Map Table.
const uint32_t VERSION
Version number.
Definition metadata.h:24
#define MAGIC_NUMBER
Magic number (little endian).
Definition metadata.h:17
The Phasor Programming Language and Runtime.
Definition AST.hpp:8
ValueType
Runtime value types for the VM.
Definition Value.hpp:17
Complete bytecode structure.
Definition CodeGen.hpp:201
std::vector< Value > constants
Constant pool.
Definition CodeGen.hpp:203
std::map< std::string, int > functionEntries
Function name -> instruction index mapping.
Definition CodeGen.hpp:205
int nextVarIndex
Next available variable index.
Definition CodeGen.hpp:206
std::map< std::string, int > variables
Variable name -> index mapping.
Definition CodeGen.hpp:204
std::vector< Instruction > instructions
List of instructions.
Definition CodeGen.hpp:202