MXVM 1.8.1
Virtual Machine, Compiler, and Pascal Frontend
Loading...
Searching...
No Matches
icode.hpp
Go to the documentation of this file.
1
6#ifndef ICODE_HPP_
7#define ICODE_HPP_
8
9#include "mxvm/instruct.hpp"
10#include "mxvm/parser.hpp"
11#include "scanner/exception.hpp"
12#include <functional>
13#include <unordered_map>
14#include <variant>
15#include <vector>
16
17namespace mxvm {
18
20 using StackValue = std::variant<int64_t, void *, double, std::string>;
21
23 class Stack {
24 public:
25 Stack() = default;
26
30 void push(const StackValue &value) {
31 data.push_back(value);
32 }
33
38 [[nodiscard]] StackValue pop() {
39 if (data.empty())
40 throw mx::Exception("Stack underflow");
41 StackValue val = data.back();
42 data.pop_back();
43 return val;
44 }
45
47 [[nodiscard]] bool empty() const { return data.empty(); }
48
50 [[nodiscard]] size_t size() const { return data.size(); }
51
57 StackValue &operator[](size_t index) {
58 if (index >= data.size())
59 throw mx::Exception("Stack index out of bounds: " + std::to_string(index));
60 return data[index];
61 }
62
63 private:
64 std::vector<StackValue> data;
65 };
66
67 class Program;
68
70 using runtime_call = std::function<void(Program *program, std::vector<Operand> &operands)>;
71
79 public:
81 RuntimeFunction() : func(nullptr), handle(nullptr) {}
82
85
88 func = r.func;
89 handle = r.handle;
91 fname = r.fname;
92 return *this;
93 }
94 ~RuntimeFunction() = default;
95
100 RuntimeFunction(const std::string &mod, const std::string &name);
101
106 void call(Program *program, std::vector<Operand> &operands);
107 void *func = nullptr;
108 void *handle = nullptr;
109 std::string mod_name;
110 std::string fname;
111 static std::unordered_map<std::string, void *> handles;
112 };
113
121 class Base {
122 public:
123 Base() = default;
125 Base(Base &&other) noexcept;
126 ~Base() = default;
128 Base &operator=(Base &&other) noexcept;
129
133 void setMainBase(Base *b) { Base::base = b; }
134
138 void add_instruction(const Instruction &i);
139
145 void add_label(const std::string &name, uint64_t address, bool f);
146
151 void add_variable(const std::string &name, const Variable &v);
152
158 void add_global(const std::string &objname, const std::string &name, const Variable &v);
159
165 void add_extern(const std::string &mod, const std::string &name, bool module);
166
173 void add_runtime_extern(const std::string &mod_name, const std::string &mod, const std::string &func_name, const std::string &name);
174
178 void add_filename(const std::string &fname);
179
184 void add_allocated(const std::string &name, Variable &v);
185
190 void add_object(const std::string &name, Program *prog);
191 std::string name;
192 std::vector<Instruction> inc;
193 std::unordered_map<std::string, Variable> vars;
194 std::unordered_map<std::string, std::pair<uint64_t, bool>> labels;
195 std::vector<ExternalFunction> external;
196 std::unordered_map<std::string, RuntimeFunction> external_functions;
197 static Base *base;
198 static std::string root_name;
199 static std::vector<std::string> filenames;
200 static std::unordered_map<std::string, Variable> allocated;
201 static std::unordered_map<std::string, Program *> object_map;
202 std::string assembly_code;
203 };
204
212 class Program : public Base {
213 public:
214 friend class Parser;
216 Program();
218 ~Program();
219
221 Program(Program &&other) noexcept
222 : Base(std::move(other)),
223 filename(std::move(other.filename)),
224 objects(std::move(other.objects)),
225 object(other.object),
226 pc(other.pc),
227 running(other.running),
228 exitCode(other.exitCode),
229 zero_flag(other.zero_flag),
230 less_flag(other.less_flag),
231 greater_flag(other.greater_flag),
232 carry_flag(other.carry_flag),
233 xmm_offset(other.xmm_offset),
234 args(std::move(other.args)),
235 main_function(other.main_function),
236 object_external(other.object_external),
237 stack(std::move(other.stack)),
238 result(std::move(other.result)),
239 parent(other.parent),
240 platform(other.platform) {
241 other.pc = 0;
242 other.running = false;
243 other.exitCode = 0;
244 for (auto &var_pair : vars) {
245 var_pair.second.obj_name = name;
246 }
247 }
248
250 Program &operator=(Program &&other) noexcept {
251 if (this != &other) {
252 Base::operator=(std::move(other));
253 filename = std::move(other.filename);
254 objects = std::move(other.objects);
255 object = other.object;
256 pc = other.pc;
257 running = other.running;
258 exitCode = other.exitCode;
259 zero_flag = other.zero_flag;
260 less_flag = other.less_flag;
261 greater_flag = other.greater_flag;
262 carry_flag = other.carry_flag;
263 xmm_offset = other.xmm_offset;
264 args = std::move(other.args);
265 main_function = other.main_function;
266 object_external = other.object_external;
267 stack = std::move(other.stack);
268 result = std::move(other.result);
269 parent = other.parent;
270 other.pc = 0;
271 other.running = false;
272 other.exitCode = 0;
273 for (auto &var_pair : vars) {
274 var_pair.second.obj_name = name;
275 }
276 platform = other.platform;
277 }
278 return *this;
279 }
280
282 void add_standard();
283
285 void stop();
286
291 int exec();
295 void print(std::ostream &out);
296
300 void post(std::ostream &out);
301
305 int getExitCode() const { return exitCode; }
306 std::string name;
307 std::string filename;
312 std::string getPlatformSymbolName(const std::string &name);
319 void generateCode(const Platform &platform, bool obj, std::ostream &out);
324 static std::string escapeNewLines(const std::string &text);
325
329 void memoryDump(std::ostream &out);
330
334 void setArgs(const std::vector<std::string> &argv);
335
339 void setObject(bool obj);
340 std::vector<std::unique_ptr<Program>> objects;
341 bool object = false;
346 bool validateNames(Validator &v);
347
351 void flatten(Program *program);
352
357 void flatten_inc(Program *root, Instruction &i);
358
365 void flatten_label(Program *root, int64_t offset, const std::string &label, bool func);
366
372 void flatten_external(Program *root, const std::string &e, RuntimeFunction &r);
373
378 std::string getMangledName(const std::string &var);
379
384 std::string getMangledName(const Operand &op);
385
390 Program *getObjectByName(const std::string &name);
391
396 bool isFunctionValid(const std::string &label);
397
398 private:
399 size_t pc;
400 bool running;
401 int exitCode = 0;
402 bool zero_flag = false;
403 bool less_flag = false;
404 bool greater_flag = false;
405 bool carry_flag = false;
406 int xmm_offset = 0;
407 std::vector<std::string> args;
409 bool object_external = false;
410
419
420 public:
428 void generateFunctionCall(std::ostream &out, const std::string &name, std::vector<Operand> &op);
429
434 void generateInvokeCall(std::ostream &out, std::vector<Operand> &op);
435
440 void generateInstruction(std::ostream &out, const Instruction &i);
441
448 int generateLoadVar(std::ostream &out, int reg, const Operand &op);
449
457 int generateLoadVar(std::ostream &out, VarType type, std::string reg, const Operand &op);
458
464 std::string getRegisterByIndex(int index, VarType type);
465 void gen_print(std::ostream &out, const Instruction &i);
466 void gen_arth(std::ostream &out, std::string arth, const Instruction &i);
467 void gen_exit(std::ostream &out, const Instruction &i);
468 void gen_mov(std::ostream &out, const Instruction &i);
469 void gen_jmp(std::ostream &out, const Instruction &i);
470 void gen_cmp(std::ostream &out, const Instruction &i);
471 void gen_alloc(std::ostream &out, const Instruction &i);
473 void gen_realloc(std::ostream &out, const Instruction &i);
474 void gen_free(std::ostream &out, const Instruction &i);
475 void gen_load(std::ostream &out, const Instruction &i);
476 void gen_store(std::ostream &out, const Instruction &i);
477 void gen_ret(std::ostream &out, const Instruction &i);
478 void gen_call(std::ostream &out, const Instruction &i);
479 void gen_done(std::ostream &out, const Instruction &i);
480 void gen_bitop(std::ostream &out, const std::string &opc, const Instruction &i);
481 void gen_not(std::ostream &out, const Instruction &i);
482 void gen_push(std::ostream &out, const Instruction &i);
483 void gen_pop(std::ostream &out, const Instruction &i);
484 void gen_stack_load(std::ostream &out, const Instruction &i);
485 void gen_stack_store(std::ostream &out, const Instruction &i);
486 void gen_stack_sub(std::ostream &out, const Instruction &i);
487 void gen_getline(std::ostream &out, const Instruction &i);
488 void gen_to_int(std::ostream &out, const Instruction &i);
489 void gen_to_float(std::ostream &out, const Instruction &i);
490 void gen_invoke(std::ostream &out, const Instruction &i);
491 void gen_return(std::ostream &out, const Instruction &i);
492 void gen_neg(std::ostream &out, const Instruction &i);
493 void gen_lea(std::ostream &out, const Instruction &i);
494 void gen_fcmp(std::ostream &out, const Instruction &i);
495 void gen_jae(std::ostream &out, const Instruction &i);
496 void gen_jbe(std::ostream &out, const Instruction &i);
497 void gen_jc(std::ostream &out, const Instruction &i);
498 void gen_jnc(std::ostream &out, const Instruction &i);
499 void gen_jp(std::ostream &out, const Instruction &i);
500 void gen_jnp(std::ostream &out, const Instruction &i);
501 void gen_jo(std::ostream &out, const Instruction &i);
502 void gen_jno(std::ostream &out, const Instruction &i);
503 void gen_js(std::ostream &out, const Instruction &i);
504 void gen_jns(std::ostream &out, const Instruction &i);
505 void gen_add(std::ostream &out, const Instruction &i);
506 void gen_sub(std::ostream &out, const Instruction &i);
507 void gen_mul(std::ostream &out, const Instruction &i);
508 void gen_div(std::ostream &out, const Instruction &i);
509 void gen_mod(std::ostream &out, const Instruction &i);
510
517 std::string gen_optimize(const std::string &code, const Platform &platform);
518
523 std::string optimize_darwin(const std::string &code);
524
529 std::string optimize_core(const std::string &code);
531
539 void x64_emit_iob_func(std::ostream &out, int index, const std::string &dstReg);
540
546 std::string x64_getRegisterByIndex(int index, VarType type);
547
554 int x64_generateLoadVar(std::ostream &out, int r, const Operand &op);
555
563 int x64_generateLoadVar(std::ostream &out, VarType type, std::string reg, const Operand &op);
564
570 void x64_generateFunctionCall(std::ostream &out, const std::string &name, std::vector<Operand> &args);
571
576 void x64_generateInvokeCall(std::ostream &out, std::vector<Operand> &op);
577
583 void x64_generateCode(const Platform &platform, bool obj, std::ostream &out);
584
589 void x64_generateInstruction(std::ostream &out, const Instruction &i);
590 void x64_gen_done(std::ostream &out, const Instruction &i);
591 void x64_gen_ret(std::ostream &out, const Instruction &i);
592 void x64_gen_return(std::ostream &out, const Instruction &i);
593 void x64_gen_neg(std::ostream &out, const Instruction &i);
594 void x64_gen_invoke(std::ostream &out, const Instruction &i);
595 void x64_gen_call(std::ostream &out, const Instruction &i);
596 void x64_gen_alloc(std::ostream &out, const Instruction &i);
598 void x64_gen_realloc(std::ostream &out, const Instruction &i);
599 void x64_gen_free(std::ostream &out, const Instruction &i);
600 void x64_gen_load(std::ostream &out, const Instruction &i);
601 void x64_gen_store(std::ostream &out, const Instruction &i);
602 void x64_gen_to_int(std::ostream &out, const Instruction &i);
603 void x64_gen_to_float(std::ostream &out, const Instruction &i);
604 void x64_gen_div(std::ostream &out, const Instruction &i);
605 void x64_gen_mod(std::ostream &out, const Instruction &i);
606 void x64_gen_getline(std::ostream &out, const Instruction &i);
607 void x64_gen_bitop(std::ostream &out, const std::string &opc, const Instruction &i);
608 void x64_gen_not(std::ostream &out, const Instruction &i);
609 void x64_gen_push(std::ostream &out, const Instruction &i);
610 void x64_gen_pop(std::ostream &out, const Instruction &i);
611 void x64_gen_stack_load(std::ostream &out, const Instruction &i);
612 void x64_gen_stack_store(std::ostream &out, const Instruction &i);
613 void x64_gen_stack_sub(std::ostream &out, const Instruction &i);
614 void x64_gen_print(std::ostream &out, const Instruction &i);
615 void x64_gen_jmp(std::ostream &out, const Instruction &i);
616 void x64_gen_cmp(std::ostream &out, const Instruction &i);
617 void x64_gen_mov(std::ostream &out, const Instruction &i);
618 void x64_gen_arth(std::ostream &out, std::string arth, const Instruction &i);
619 void x64_gen_exit(std::ostream &out, const Instruction &i);
620 void x64_gen_lea(std::ostream &out, const Instruction &i);
621 void x64_gen_fcmp(std::ostream &out, const Instruction &i);
622 void x64_gen_jae(std::ostream &out, const Instruction &i);
623 void x64_gen_jbe(std::ostream &out, const Instruction &i);
624 void x64_gen_jc(std::ostream &out, const Instruction &i);
625 void x64_gen_jnc(std::ostream &out, const Instruction &i);
626 void x64_gen_jp(std::ostream &out, const Instruction &i);
627 void x64_gen_jnp(std::ostream &out, const Instruction &i);
628 void x64_gen_jo(std::ostream &out, const Instruction &i);
629 void x64_gen_jno(std::ostream &out, const Instruction &i);
630 void x64_gen_js(std::ostream &out, const Instruction &i);
631 void x64_gen_jns(std::ostream &out, const Instruction &i);
632
633 std::unordered_map<std::string, std::string> x64_reg_vars;
634 std::vector<std::string> x64_reg_save_order;
635
639 void x64_analyzeRegAlloc(bool uses_std_module);
640
642 void x64_emitFlushRegs(std::ostream &out);
643
645 void x64_emitReloadRegs(std::ostream &out);
646
648 void x64_emitSaveRegs(std::ostream &out);
649
651 void x64_emitRestoreRegs(std::ostream &out);
652
658 void x64_emitStoreVar(std::ostream &out, const std::string &srcReg, const Operand &dest);
659
665 void x64_emitStoreVarImm(std::ostream &out, const std::string &imm, const Operand &dest);
666
672 void x64_emitLoadVar(std::ostream &out, const std::string &dstReg, const Operand &src);
674
677 std::unordered_map<std::string, std::string> sysv_reg_vars;
678 std::vector<std::string> sysv_reg_save_order;
679
683 void sysv_analyzeRegAlloc(bool uses_std_module);
684
686 void sysv_emitFlushRegs(std::ostream &out);
687
689 void sysv_emitReloadRegs(std::ostream &out);
690
692 void sysv_emitSaveRegs(std::ostream &out);
693
695 void sysv_emitRestoreRegs(std::ostream &out);
696
702 void sysv_emitStoreVar(std::ostream &out, const std::string &srcReg, const Operand &dest);
703
709 void sysv_emitStoreVarImm(std::ostream &out, const std::string &imm, const Operand &dest);
710
716 void sysv_emitLoadVar(std::ostream &out, const std::string &dstReg, const Operand &src);
718
721 void exec_mov(const Instruction &instr);
722 void exec_add(const Instruction &instr);
723 void exec_sub(const Instruction &instr);
724 void exec_mul(const Instruction &instr);
725 void exec_div(const Instruction &instr);
726 void exec_cmp(const Instruction &instr);
727 void exec_jmp(const Instruction &instr);
728 void exec_load(const Instruction &instr);
729 void exec_store(const Instruction &instr);
730 void exec_or(const Instruction &instr);
731 void exec_and(const Instruction &instr);
732 void exec_xor(const Instruction &instr);
733 void exec_not(const Instruction &instr);
734 void exec_mod(const Instruction &instr);
735 void exec_je(const Instruction &instr);
736 void exec_jne(const Instruction &instr);
737 void exec_jl(const Instruction &instr);
738 void exec_jle(const Instruction &instr);
739 void exec_jg(const Instruction &instr);
740 void exec_jge(const Instruction &instr);
741 void exec_jz(const Instruction &instr);
742 void exec_jnz(const Instruction &instr);
743 void exec_ja(const Instruction &instr);
744 void exec_jb(const Instruction &instr);
745 void exec_print(const Instruction &instr);
746 void exec_string_print(const Instruction &instr);
747 void exec_exit(const Instruction &instr);
748 void exec_alloc(const Instruction &instr);
749 void exec_free(const Instruction &instr);
750 void exec_getline(const Instruction &instr);
751 void exec_push(const Instruction &instr);
752 void exec_pop(const Instruction &instr);
753 void exec_stack_load(const Instruction &instr);
754 void exec_stack_store(const Instruction &instr);
755 void exec_stack_sub(const Instruction &instr);
756 void exec_call(const Instruction &instr);
757 void exec_ret(const Instruction &instr);
758 void exec_done(const Instruction &instr);
759 void exec_to_int(const Instruction &instr);
760 void exec_to_float(const Instruction &instr);
761 void exec_invoke(const Instruction &instr);
762 void exec_return(const Instruction &instr);
763 void exec_lea(const Instruction &instr);
764 void exec_neg(const Instruction &instr);
773 void exec_realloc(const Instruction &instr);
774 void exec_fcmp(const Instruction &instr);
775 void exec_jae(const Instruction &instr);
776 void exec_jbe(const Instruction &instr);
777 void exec_jc(const Instruction &instr);
778 void exec_jnc(const Instruction &instr);
779 void exec_jp(const Instruction &instr);
780 void exec_jnp(const Instruction &instr);
781 void exec_jo(const Instruction &instr);
782 void exec_jno(const Instruction &instr);
783 void exec_js(const Instruction &instr);
784 void exec_jns(const Instruction &instr);
786
794 Variable &getVariable(const std::string &name);
795
800 bool isVariable(const std::string &name);
801
806 void setVariableFromString(Variable &var, const std::string &value);
807
813 void addVariables(Variable &dest, Variable &src1, Variable &src2);
814
816 void subVariables(Variable &dest, Variable &src1, Variable &src2);
817
819 void mulVariables(Variable &dest, Variable &src1, Variable &src2);
820
822 void divVariables(Variable &dest, Variable &src1, Variable &src2);
823
830 std::string printFormatted(const std::string &format, const std::vector<Variable *> &args, bool output = true);
831
836 void setVariableFromConstant(Variable &var, const std::string &value);
837
843 Variable createTempVariable(VarType type, const std::string &value);
844
849 bool isConstant(const std::string &value);
850
857
860 Program *parent = nullptr;
867 size_t x64_reserve_call_area(std::ostream &out, size_t spill_bytes);
868
873 void x64_release_call_area(std::ostream &out, size_t frame);
874
879 void x64_direct_stack_adjust(std::ostream &out, int64_t bytes);
882 };
883
888 void except_assert(std::string reason, bool value);
889
894 bool isFunctionReturningOwnedPtr(const std::string &funcName);
895
896} // namespace mxvm
897
898#endif
General-purpose exception with errno-aware factory method.
Definition exception.hpp:38
static std::unordered_map< std::string, Program * > object_map
object name -> Program mapping
Definition icode.hpp:201
void add_global(const std::string &objname, const std::string &name, const Variable &v)
Declare a global variable scoped to an object.
Definition icode.cpp:254
void add_filename(const std::string &fname)
Record a source filename for debug/error reporting.
Definition icode.cpp:257
std::unordered_map< std::string, std::pair< uint64_t, bool > > labels
label -> (address, is_function)
Definition icode.hpp:194
std::vector< Instruction > inc
instruction stream
Definition icode.hpp:192
~Base()=default
void add_runtime_extern(const std::string &mod_name, const std::string &mod, const std::string &func_name, const std::string &name)
Register and resolve a runtime-loaded external function.
Definition icode.cpp:273
void add_variable(const std::string &name, const Variable &v)
Declare a local variable in the symbol table.
Definition icode.cpp:246
void add_allocated(const std::string &name, Variable &v)
Track a heap-allocated variable for cleanup.
Definition icode.cpp:90
void setMainBase(Base *b)
Set the root program base pointer (used for global variable lookup).
Definition icode.hpp:133
void add_extern(const std::string &mod, const std::string &name, bool module)
Register an external function import.
Definition icode.cpp:266
void add_object(const std::string &name, Program *prog)
Register a child object program.
Definition icode.cpp:136
std::unordered_map< std::string, Variable > vars
variable symbol table
Definition icode.hpp:193
std::string assembly_code
generated assembly output for objects
Definition icode.hpp:202
Base & operator=(Base &&other) noexcept
Move-assignment operator.
Definition icode.cpp:76
void add_label(const std::string &name, uint64_t address, bool f)
Register a label at the given instruction address.
Definition icode.cpp:241
static Base * base
pointer to the main program base
Definition icode.hpp:197
static std::vector< std::string > filenames
Definition icode.hpp:199
std::string name
Definition icode.hpp:191
Base()=default
std::unordered_map< std::string, RuntimeFunction > external_functions
resolved runtime function bindings
Definition icode.hpp:196
static std::unordered_map< std::string, Variable > allocated
heap-allocated variables
Definition icode.hpp:200
void add_instruction(const Instruction &i)
Append an instruction to the instruction stream.
Definition icode.cpp:237
static std::string root_name
Definition icode.hpp:198
std::vector< ExternalFunction > external
declared external function imports
Definition icode.hpp:195
Complete MXVM program: instruction interpreter and native x64 code generator.
Definition icode.hpp:212
Variable createTempVariable(VarType type, const std::string &value)
Create a temporary unnamed variable with the given type and value.
void gen_jp(std::ostream &out, const Instruction &i)
void setVariableFromConstant(Variable &var, const std::string &value)
Set a variable's value from a constant string (integer, float, or string literal).
void gen_lea(std::ostream &out, const Instruction &i)
void exec_jns(const Instruction &instr)
void exec_jae(const Instruction &instr)
Variable & getVariable(const std::string &name)
Look up a variable by name, searching local scope then global.
void exec_mul(const Instruction &instr)
void x64_generateInstruction(std::ostream &out, const Instruction &i)
Dispatch a single instruction to its Win64 code generator.
void exec_jc(const Instruction &instr)
void x64_gen_load(std::ostream &out, const Instruction &i)
void x64_gen_jae(std::ostream &out, const Instruction &i)
void sysv_emitSaveRegs(std::ostream &out)
Save callee-saved registers at function prologue.
Definition icode_gen.cpp:79
void exec_free(const Instruction &instr)
void exec_load(const Instruction &instr)
int exec()
Execute the program via the interpreter.
void exec_exit(const Instruction &instr)
void sysv_emitFlushRegs(std::ostream &out)
Write all register-allocated variables back to memory.
Definition icode_gen.cpp:67
void x64_gen_getline(std::ostream &out, const Instruction &i)
void x64_gen_free(std::ostream &out, const Instruction &i)
void flatten_label(Program *root, int64_t offset, const std::string &label, bool func)
Copy a label from a child object into the root label map with an address offset.
void x64_gen_pop(std::ostream &out, const Instruction &i)
void x64_gen_print(std::ostream &out, const Instruction &i)
void divVariables(Variable &dest, Variable &src1, Variable &src2)
Divide src1 by src2 and store the result in dest.
void exec_push(const Instruction &instr)
Execute a PUSH instruction — save a variable or constant onto the VM stack.
void stop()
Halt the interpreter loop.
void x64_gen_jc(std::ostream &out, const Instruction &i)
void x64_gen_neg(std::ostream &out, const Instruction &i)
void gen_cmp(std::ostream &out, const Instruction &i)
VarType last_call_ret_type
Definition icode.hpp:881
void x64_emitStoreVar(std::ostream &out, const std::string &srcReg, const Operand &dest)
Store a register value into a variable (register-allocated or memory).
Stack stack
Definition icode.hpp:858
std::vector< std::string > sysv_reg_save_order
Definition icode.hpp:678
bool isFunctionValid(const std::string &label)
Check whether a label exists and is marked as a function entry.
Definition icode.cpp:175
void gen_jc(std::ostream &out, const Instruction &i)
void x64_emitStoreVarImm(std::ostream &out, const std::string &imm, const Operand &dest)
Store an immediate value into a variable.
void x64_gen_to_float(std::ostream &out, const Instruction &i)
void x64_emitSaveRegs(std::ostream &out)
Save callee-saved registers at function prologue.
int x64_generateLoadVar(std::ostream &out, int r, const Operand &op)
Load a variable or constant into a numbered Win64 register.
void x64_gen_mov(std::ostream &out, const Instruction &i)
size_t pc
program counter
Definition icode.hpp:399
bool less_flag
comparison less-than flag
Definition icode.hpp:403
Program * getObjectByName(const std::string &name)
Look up a child object program by name.
Definition icode.cpp:285
void exec_mod(const Instruction &instr)
void exec_jg(const Instruction &instr)
void x64_gen_jns(std::ostream &out, const Instruction &i)
void x64_emit_iob_func(std::ostream &out, int index, const std::string &dstReg)
Emit an integer-or-byte function argument load for Win64 ABI.
void sysv_emitRestoreRegs(std::ostream &out)
Restore callee-saved registers at function epilogue.
Definition icode_gen.cpp:85
void add_standard()
Register standard library runtime functions.
Definition icode.cpp:107
void gen_add(std::ostream &out, const Instruction &i)
void exec_jl(const Instruction &instr)
std::string optimize_darwin(const std::string &code)
Darwin-specific assembly optimizations.
void exec_stack_load(const Instruction &instr)
void x64_gen_ret(std::ostream &out, const Instruction &i)
bool isVariable(const std::string &name)
Check whether a variable exists in local or global scope.
void x64_gen_cmp(std::ostream &out, const Instruction &i)
void sysv_emitStoreVar(std::ostream &out, const std::string &srcReg, const Operand &dest)
Store a register value into a variable (register-allocated or memory).
Definition icode_gen.cpp:91
void x64_gen_jp(std::ostream &out, const Instruction &i)
void gen_pop(std::ostream &out, const Instruction &i)
Emit x86-64 POP into a variable.
void gen_not(std::ostream &out, const Instruction &i)
void gen_return(std::ostream &out, const Instruction &i)
std::unordered_map< std::string, std::string > x64_reg_vars
Win64 variable-to-register mapping.
Definition icode.hpp:633
void exec_to_int(const Instruction &instr)
void x64_release_call_area(std::ostream &out, size_t frame)
Release a Win64 call frame previously reserved.
void gen_jno(std::ostream &out, const Instruction &i)
void exec_jz(const Instruction &instr)
void x64_gen_stack_store(std::ostream &out, const Instruction &i)
void gen_realloc(std::ostream &out, const Instruction &i)
Generate System V x86-64 assembly for the REALLOC instruction (dynamic array resize).
void exec_fcmp(const Instruction &instr)
void gen_jns(std::ostream &out, const Instruction &i)
std::vector< std::string > args
Definition icode.hpp:407
~Program()
Destructor — frees any heap-allocated variables.
Definition icode.cpp:144
static std::string escapeNewLines(const std::string &text)
Escape newline characters in a string literal for assembly output.
Definition icode.cpp:296
void gen_call(std::ostream &out, const Instruction &i)
void flatten_external(Program *root, const std::string &e, RuntimeFunction &r)
Copy an external function binding from a child object into the root.
void print(std::ostream &out)
Print all instructions and data to an output stream.
std::string getPlatformSymbolName(const std::string &name)
Mangle a symbol name with the platform prefix (e.g. _name for Darwin).
Definition icode_gen.cpp:14
void post(std::ostream &out)
Generate native data section (variable declarations) into the output stream.
void exec_to_float(const Instruction &instr)
void exec_done(const Instruction &instr)
std::string filename
Definition icode.hpp:307
void exec_store(const Instruction &instr)
Execute a STORE instruction — write a value into a pointer at a given offset.
Platform platform
Definition icode.hpp:861
bool last_call_returns_owned_ptr
tracks ownership of last call's return value
Definition icode.hpp:418
void gen_push(std::ostream &out, const Instruction &i)
Emit x86-64 PUSH for a variable or constant.
void exec_sub(const Instruction &instr)
void sysv_analyzeRegAlloc(bool uses_std_module)
Analyze variable usage and assign System V callee-saved registers.
Definition icode_gen.cpp:24
std::unordered_map< std::string, std::string > sysv_reg_vars
SysV variable-to-register mapping.
Definition icode.hpp:677
void x64_gen_to_int(std::ostream &out, const Instruction &i)
void exec_or(const Instruction &instr)
std::vector< std::unique_ptr< Program > > objects
Definition icode.hpp:340
void gen_invoke(std::ostream &out, const Instruction &i)
void setObject(bool obj)
Mark this program as an object (no main entry point).
Definition icode.cpp:132
void exec_mov(const Instruction &instr)
void sysv_emitLoadVar(std::ostream &out, const std::string &dstReg, const Operand &src)
Load a variable into a destination register.
void exec_return(const Instruction &instr)
void x64_gen_not(std::ostream &out, const Instruction &i)
void gen_done(std::ostream &out, const Instruction &i)
std::string getMangledName(const std::string &var)
Mangle a variable name with its owning object prefix.
Definition icode.cpp:22
void exec_not(const Instruction &instr)
bool carry_flag
comparison carry flag
Definition icode.hpp:405
void generateCode(const Platform &platform, bool obj, std::ostream &out)
Generate native x64 assembly for the entire program.
LastCmpType last_cmp_type
Definition icode.hpp:417
void exec_cmp(const Instruction &instr)
void x64_gen_jno(std::ostream &out, const Instruction &i)
void gen_to_int(std::ostream &out, const Instruction &i)
void generateInstruction(std::ostream &out, const Instruction &i)
Dispatch a single instruction to its System V code generator.
bool main_function
true if this program has a main entry point
Definition icode.hpp:408
void x64_gen_return(std::ostream &out, const Instruction &i)
void gen_stack_load(std::ostream &out, const Instruction &i)
std::vector< std::string > x64_reg_save_order
Definition icode.hpp:634
void exec_je(const Instruction &instr)
void x64_gen_arth(std::ostream &out, std::string arth, const Instruction &i)
void exec_invoke(const Instruction &instr)
void exec_js(const Instruction &instr)
void x64_gen_invoke(std::ostream &out, const Instruction &i)
void x64_emitReloadRegs(std::ostream &out)
Reload register-allocated variables from memory.
LastCmpType
Tracks type of last comparison for conditional jumps.
Definition icode.hpp:412
size_t x64_reserve_call_area(std::ostream &out, size_t spill_bytes)
Reserve stack space for a Win64 call frame including spill area.
void gen_jnc(std::ostream &out, const Instruction &i)
void exec_jo(const Instruction &instr)
Variable variableFromOperand(const Operand &op)
Resolve an Operand to its corresponding Variable.
void exec_realloc(const Instruction &instr)
Execute the REALLOC instruction in the interpreter.
void exec_add(const Instruction &instr)
void exec_and(const Instruction &instr)
void x64_gen_jnp(std::ostream &out, const Instruction &i)
void exec_xor(const Instruction &instr)
Program & operator=(Program &&other) noexcept
Move-assignment operator.
Definition icode.hpp:250
void memoryDump(std::ostream &out)
Dump all variable values to a stream for debugging.
Definition icode.cpp:316
void exec_jnz(const Instruction &instr)
void x64_emitLoadVar(std::ostream &out, const std::string &dstReg, const Operand &src)
Load a variable into a destination register.
void gen_mov(std::ostream &out, const Instruction &i)
void gen_mod(std::ostream &out, const Instruction &i)
std::string x64_getRegisterByIndex(int index, VarType type)
Get the Win64 register name for a given index and variable type.
std::string name
Definition icode.hpp:306
void flatten(Program *program)
Flatten child object programs into the root instruction stream.
void x64_gen_call(std::ostream &out, const Instruction &i)
void exec_neg(const Instruction &instr)
void gen_jmp(std::ostream &out, const Instruction &i)
void x64_gen_alloc(std::ostream &out, const Instruction &i)
void x64_gen_jmp(std::ostream &out, const Instruction &i)
void sysv_emitReloadRegs(std::ostream &out)
Reload register-allocated variables from memory.
Definition icode_gen.cpp:73
void gen_arth(std::ostream &out, std::string arth, const Instruction &i)
std::string gen_optimize(const std::string &code, const Platform &platform)
Peephole optimizer for generated assembly.
void gen_jo(std::ostream &out, const Instruction &i)
void x64_gen_jnc(std::ostream &out, const Instruction &i)
void exec_stack_sub(const Instruction &instr)
bool isConstant(const std::string &value)
Check whether a string represents a compile-time constant (number or quoted string).
bool object_external
Definition icode.hpp:409
void x64_generateInvokeCall(std::ostream &out, std::vector< Operand > &op)
Generate a Win64 dynamic invoke call.
void exec_call(const Instruction &instr)
void gen_free(std::ostream &out, const Instruction &i)
void exec_string_print(const Instruction &instr)
void gen_mul(std::ostream &out, const Instruction &i)
void exec_jne(const Instruction &instr)
void gen_js(std::ostream &out, const Instruction &i)
void exec_jge(const Instruction &instr)
void exec_div(const Instruction &instr)
void exec_jmp(const Instruction &instr)
bool zero_flag
comparison zero flag
Definition icode.hpp:402
void x64_gen_jbe(std::ostream &out, const Instruction &i)
void exec_jle(const Instruction &instr)
void gen_div(std::ostream &out, const Instruction &i)
void gen_jbe(std::ostream &out, const Instruction &i)
void exec_getline(const Instruction &instr)
void gen_sub(std::ostream &out, const Instruction &i)
void exec_alloc(const Instruction &instr)
std::string optimize_core(const std::string &code)
Platform-independent peephole optimizations.
void gen_stack_store(std::ostream &out, const Instruction &i)
void gen_jae(std::ostream &out, const Instruction &i)
void exec_jbe(const Instruction &instr)
int getExitCode() const
Get the program's exit code after execution.
Definition icode.hpp:305
void x64_gen_mod(std::ostream &out, const Instruction &i)
void exec_jb(const Instruction &instr)
void x64_gen_stack_load(std::ostream &out, const Instruction &i)
friend class Parser
Definition icode.hpp:214
void generateInvokeCall(std::ostream &out, std::vector< Operand > &op)
Generate a dynamic invoke call (runtime-resolved external function).
void x64_gen_stack_sub(std::ostream &out, const Instruction &i)
void x64_gen_done(std::ostream &out, const Instruction &i)
void generateFunctionCall(std::ostream &out, const std::string &name, std::vector< Operand > &op)
Generate a System V ABI function call with operands as arguments.
void x64_gen_fcmp(std::ostream &out, const Instruction &i)
void exec_jnp(const Instruction &instr)
bool greater_flag
comparison greater-than flag
Definition icode.hpp:404
void gen_bitop(std::ostream &out, const std::string &opc, const Instruction &i)
void gen_store(std::ostream &out, const Instruction &i)
bool last_call_returns_owned
Definition icode.hpp:880
void exec_lea(const Instruction &instr)
void addVariables(Variable &dest, Variable &src1, Variable &src2)
Add two variables and store the result in dest.
void gen_getline(std::ostream &out, const Instruction &i)
void flatten_inc(Program *root, Instruction &i)
Rewrite object-qualified operand references in a single instruction.
bool validateNames(Validator &v)
Validate all variable and label names against the Validator.
int xmm_offset
current XMM register allocation offset
Definition icode.hpp:406
Operand result
return value operand from last invoke
Definition icode.hpp:859
void exec_jno(const Instruction &instr)
void exec_ja(const Instruction &instr)
void x64_gen_div(std::ostream &out, const Instruction &i)
void x64_gen_js(std::ostream &out, const Instruction &i)
void exec_pop(const Instruction &instr)
Execute a POP instruction — restore a value from the VM stack into a variable.
void x64_gen_jo(std::ostream &out, const Instruction &i)
void gen_to_float(std::ostream &out, const Instruction &i)
void gen_stack_sub(std::ostream &out, const Instruction &i)
void exec_jp(const Instruction &instr)
void x64_gen_push(std::ostream &out, const Instruction &i)
void mulVariables(Variable &dest, Variable &src1, Variable &src2)
Multiply two variables and store the result in dest.
void x64_gen_exit(std::ostream &out, const Instruction &i)
void gen_alloc(std::ostream &out, const Instruction &i)
void gen_jnp(std::ostream &out, const Instruction &i)
Program()
Default constructor — initializes execution state (pc, flags, etc.).
Definition icode.cpp:96
void gen_exit(std::ostream &out, const Instruction &i)
void gen_load(std::ostream &out, const Instruction &i)
void x64_gen_bitop(std::ostream &out, const std::string &opc, const Instruction &i)
void x64_emitRestoreRegs(std::ostream &out)
Restore callee-saved registers at function epilogue.
std::string getRegisterByIndex(int index, VarType type)
Get the register name for a given index and variable type.
void setVariableFromString(Variable &var, const std::string &value)
Set a variable's value from a string representation, coercing types.
void setArgs(const std::vector< std::string > &argv)
Set the command-line arguments available to the program.
Definition icode.cpp:128
void x64_analyzeRegAlloc(bool uses_std_module)
Analyze variable usage and assign Win64 callee-saved registers.
void exec_jnc(const Instruction &instr)
void gen_print(std::ostream &out, const Instruction &i)
std::string printFormatted(const std::string &format, const std::vector< Variable * > &args, bool output=true)
Format and optionally print a printf-style format string with variable arguments.
Program * parent
parent program (for object programs)
Definition icode.hpp:860
void gen_ret(std::ostream &out, const Instruction &i)
void exec_print(const Instruction &instr)
Program(Program &&other) noexcept
Move constructor — transfers all execution state and child objects.
Definition icode.hpp:221
void exec_ret(const Instruction &instr)
bool running
interpreter running flag
Definition icode.hpp:400
void x64_gen_realloc(std::ostream &out, const Instruction &i)
Generate Win64 x86-64 assembly for the REALLOC instruction (dynamic array resize).
void exec_stack_store(const Instruction &instr)
void x64_generateCode(const Platform &platform, bool obj, std::ostream &out)
Top-level Win64 code generation entry point.
void subVariables(Variable &dest, Variable &src1, Variable &src2)
Subtract src2 from src1 and store the result in dest.
void x64_generateFunctionCall(std::ostream &out, const std::string &name, std::vector< Operand > &args)
Generate a Win64 ABI function call with operands as arguments.
void x64_direct_stack_adjust(std::ostream &out, int64_t bytes)
Emit a direct stack pointer adjustment.
void gen_fcmp(std::ostream &out, const Instruction &i)
void sysv_emitStoreVarImm(std::ostream &out, const std::string &imm, const Operand &dest)
Store an immediate value into a variable.
void x64_gen_lea(std::ostream &out, const Instruction &i)
void gen_neg(std::ostream &out, const Instruction &i)
void x64_gen_store(std::ostream &out, const Instruction &i)
void x64_emitFlushRegs(std::ostream &out)
Write all register-allocated variables back to memory.
int generateLoadVar(std::ostream &out, int reg, const Operand &op)
Load a variable or constant into a numbered register.
Wraps a dynamically loaded native function from a shared library module.
Definition icode.hpp:78
RuntimeFunction(const RuntimeFunction &r)
Copy constructor.
Definition icode.hpp:84
RuntimeFunction()
Default constructor — null function pointer and handle.
Definition icode.hpp:81
std::string fname
function symbol name
Definition icode.hpp:110
void * handle
dlopen handle
Definition icode.hpp:108
void call(Program *program, std::vector< Operand > &operands)
Invoke the loaded function.
Definition icode.cpp:224
static std::unordered_map< std::string, void * > handles
cached library handles
Definition icode.hpp:111
void * func
resolved function pointer
Definition icode.hpp:107
RuntimeFunction & operator=(const RuntimeFunction &r)
Copy-assignment operator.
Definition icode.hpp:87
std::string mod_name
module name
Definition icode.hpp:109
~RuntimeFunction()=default
Runtime operand stack for the MXVM interpreter.
Definition icode.hpp:23
Stack()=default
StackValue & operator[](size_t index)
Random access into the stack.
Definition icode.hpp:57
StackValue pop()
Pop and return the top value.
Definition icode.hpp:38
size_t size() const
Return the number of elements on the stack.
Definition icode.hpp:50
bool empty() const
Check whether the stack is empty.
Definition icode.hpp:47
void push(const StackValue &value)
Push a value onto the stack.
Definition icode.hpp:30
std::vector< StackValue > data
Definition icode.hpp:64
Validates MXVM source for correct variable/label usage and instruction operands.
Definition valid.hpp:69
Exception class, hex formatting utilities, and terminal color definitions.
Parser that tokenizes and parses MXVM source into programs, handles modules/objects,...
Instruction set enum, operand/instruction structs, variable types, and Variable/Variable_Value defini...
const char * argv(int idx)
Return the command-line argument at the given index.
Definition std.c:76
Definition ast.hpp:14
std::function< void(Program *program, std::vector< Operand > &operands)> runtime_call
Callback type for runtime-registered native functions.
Definition icode.hpp:70
bool isFunctionReturningOwnedPtr(const std::string &funcName)
Check whether a named function returns an owned (heap-allocated) pointer.
Platform
Target platform for native code generation.
Definition parser.hpp:42
void except_assert(std::string reason, bool value)
Assert a condition, throwing an Exception with the given reason on failure.
Definition icode.cpp:436
std::variant< int64_t, void *, double, std::string > StackValue
Stack element: integer, pointer, double, or string.
Definition icode.hpp:20
VarType
MXVM variable type discriminator.
Definition instruct.hpp:180
A complete MXVM instruction with opcode, operands, and optional label.
Definition instruct.hpp:168
A single instruction operand (constant value or variable reference).
Definition instruct.hpp:159
A named variable with type, value, and optional object association.
Definition instruct.hpp:292