Phasor 3.1.1
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;
159 COMPILE_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:
163 COMPILE_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
170void BytecodeSerializer::writeVariableMapping(const std::map<std::string, int> &variables, int nextVarIndex)
171{
173 writeUInt32(static_cast<uint32_t>(variables.size()));
174 writeInt32(nextVarIndex);
175
176 for (const auto &[name, index] : variables)
177 {
178 writeString(name);
179 writeInt32(index);
180 }
181}
182
183void BytecodeSerializer::writeInstructions(const std::vector<Instruction> &instructions)
184{
186 writeUInt32(static_cast<uint32_t>(instructions.size()));
187
188 for (const auto &instr : instructions)
189 {
190 writeUInt8(static_cast<uint8_t>(instr.op));
191 writeInt32(instr.operand1);
192 writeInt32(instr.operand2);
193 writeInt32(instr.operand3);
194 }
195}
196
197void BytecodeSerializer::writeFunctionEntries(const std::map<std::string, int> &functionEntries)
198{
200 writeUInt32(static_cast<uint32_t>(functionEntries.size()));
201
202 for (const auto &[name, address] : functionEntries)
203 {
204 writeString(name);
205 writeInt32(address);
206 }
207}
208
209std::vector<uint8_t> BytecodeSerializer::serialize(const Bytecode &bytecode)
210{
211 buffer.clear();
212
213 for (int i = 0; i < 16; i++)
214 {
215 buffer.push_back(0);
216 }
217
218 // Write all sections
219 size_t dataStartPos = buffer.size();
221 writeVariableMapping(bytecode.variables, bytecode.nextVarIndex);
224
225 // Calculate checksum of data (everything after header)
226 std::vector<uint8_t> dataSection(buffer.begin() + dataStartPos, buffer.end());
227 uint32_t checksum = calculateCRC32(dataSection);
228
229 // Write header at the beginning
230 std::vector<uint8_t> tempBuffer = buffer;
231 buffer.clear();
232 writeHeader(checksum);
233
234 // Append the data sections
235 buffer.insert(buffer.end(), tempBuffer.begin() + 16, tempBuffer.end());
236
237 return buffer;
238}
239
240bool BytecodeSerializer::saveToFile(const Bytecode &bytecode, const std::filesystem::path &filename)
241{
242 try
243 {
244 std::vector<uint8_t> data = serialize(bytecode);
245
246 std::ofstream file(filename, std::ios::binary);
247 if (!file.is_open())
248 {
249 return false;
250 }
251
252 file.write(reinterpret_cast<const char *>(data.data()), data.size());
253 file.close();
254
255 return true;
256 }
257 catch (const std::exception &)
258 {
259 return false;
260 }
261}
262} // 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:22
#define MAGIC_NUMBER
Magic number (little endian).
Definition metadata.h:15
The Phasor Programming Language and Runtime.
Definition AST.hpp:11
ValueType
Runtime value types for the VM.
Definition Value.hpp:51
Complete bytecode structure.
Definition CodeGen.hpp:47
std::vector< Value > constants
Constant pool.
Definition CodeGen.hpp:49
std::map< std::string, int > functionEntries
Function name -> instruction index mapping.
Definition CodeGen.hpp:51
int nextVarIndex
Next available variable index.
Definition CodeGen.hpp:53
std::map< std::string, int > variables
Variable name -> index mapping.
Definition CodeGen.hpp:50
std::vector< Instruction > instructions
List of instructions.
Definition CodeGen.hpp:48