History

Rename sh program to exec.

arr committed 10 years ago

Commit 0673df81 parent 330522f4 files · +6 −6Browse files

Showing the changes to src/exec/main.cpp (1 of 4 files). Show all

Unified · Split

src/exec/main.cpp+173−0
@@ -0,0 +1,173 @@
1+//
2+// Dis VM - exec program
3+// File: main.cpp
4+// Author: arr
5+//
6+
7+#include <cstdio>
8+#include <cassert>
9+#include <array>
10+#include <disvm.h>
11+#include <builtin_module.h>
12+#include <debug.h>
13+
14+using namespace disvm;
15+using namespace disvm::runtime;
16+
17+namespace
18+{
19+ // Entry frame layout
20+ struct vm_entry_frame_t final : public vm_frame_base_alloc_t
21+ {
22+ word_t noret;
23+ pointer_t command_module_ref;
24+ pointer_t command_stack_frame;
25+ };
26+
27+ const auto entry_frame_pointer_map = std::vector<byte_t>{ 0x06 };
28+
29+ std::shared_ptr<const runtime::vm_module_t> command_module;
30+
31+ std::unique_ptr<vm_module_t> create_entry_module(disvm::vm_t &vm, int argc, char* argv[])
32+ {
33+ if (argc == 0)
34+ return{};
35+
36+ // First argument is the module to load
37+ auto command_module_path = new vm_string_t{ std::strlen(argv[0]), reinterpret_cast<uint8_t *>(argv[0]) };
38+
39+ // Pre-load the command module in the VM.
40+ command_module = vm.load_module(command_module_path->str());
41+
42+ // Convert arguments to a list
43+ vm_list_t *args = nullptr;
44+ vm_list_t *last = nullptr;
45+ for (auto i = 1; i < argc; ++i)
46+ {
47+ auto tmp = argv[i];
48+ auto arg = new vm_string_t{ std::strlen(tmp), reinterpret_cast<uint8_t *>(tmp) };
49+ if (args == nullptr)
50+ {
51+ assert(last == nullptr);
52+ args = new vm_list_t{ intrinsic_type_desc::type<vm_string_t>() };
53+ last = args;
54+ }
55+ else
56+ {
57+ auto new_tail = new vm_list_t{ intrinsic_type_desc::type<vm_string_t>() };
58+ last->set_tail(new_tail);
59+ new_tail->release();
60+
61+ last = new_tail;
62+ }
63+
64+ pt_ref(last->value()) = arg->get_allocation();
65+ }
66+
67+ // Create the module
68+ auto entry_module = std::make_unique<vm_module_t>();
69+ auto &e = *entry_module;
70+
71+ // Header details
72+ e.header.entry_pc = 0;
73+ e.header.entry_type = 0;
74+ e.header.runtime_flag = (runtime_flags_t::has_import);
75+
76+ // Inherit the stack extent from the command module and add the entry frame size.
77+ e.header.stack_extent = command_module->header.stack_extent + sizeof(vm_entry_frame_t);
78+
79+ e.type_section =
80+ {
81+ type_descriptor_t::create(sizeof(vm_entry_frame_t), entry_frame_pointer_map)
82+ };
83+
84+ // Initialize the module base register
85+ const auto mp_type = type_descriptor_t::create(12, { 0xe0 });
86+ e.original_mp.reset(vm_alloc_t::allocate(mp_type, vm_alloc_t::zero_memory));
87+ auto mp_base = e.original_mp->get_allocation<pointer_t>();
88+ mp_base[0] = command_module_path->get_allocation();
89+
90+ // [TODO] Implement the UI context for the command
91+ mp_base[1] = nullptr;
92+ mp_base[2] = args->get_allocation();
93+
94+ e.code_section =
95+ {
96+ { vm_exec_op_t
97+ {
98+ opcode_t::load,
99+ { address_mode_t::offset_indirect_mp, 0, 0 }, // command module path
100+ { address_mode_middle_t::small_immediate, 0 },
101+ { address_mode_t::offset_indirect_fp, 20, 0 } // module reference
102+ }
103+ },
104+ { vm_exec_op_t
105+ {
106+ opcode_t::mframe,
107+ { address_mode_t::offset_indirect_fp, 20, 0 }, // module reference
108+ { address_mode_middle_t::small_immediate, 0 },
109+ { address_mode_t::offset_indirect_fp, 24, 0 } // module call frame
110+ }
111+ },
112+ { vm_exec_op_t
113+ {
114+ opcode_t::movp,
115+ { address_mode_t::offset_indirect_mp, 4, 0 }, // UI context
116+ { address_mode_middle_t::none },
117+ { address_mode_t::offset_double_indirect_fp, 24, 32 } // module call frame -> UI context offset
118+ }
119+ },
120+ { vm_exec_op_t
121+ {
122+ opcode_t::movp,
123+ { address_mode_t::offset_indirect_mp, 8, 0 }, // Argument list
124+ { address_mode_middle_t::none },
125+ { address_mode_t::offset_double_indirect_fp, 24, 36 } // module call frame -> argument list offset
126+ }
127+ },
128+ { vm_exec_op_t
129+ {
130+ opcode_t::mcall,
131+ { address_mode_t::offset_indirect_fp, 24, 0 }, // module call frame
132+ { address_mode_middle_t::small_immediate, 0 },
133+ { address_mode_t::offset_indirect_fp, 20, 0 } // module reference
134+ }
135+ },
136+ { vm_exec_op_t{ opcode_t::ret,{ address_mode_t::none },{ address_mode_middle_t::none },{ address_mode_t::none } } },
137+ };
138+
139+ // Create import section for Command
140+ // See limbo/Command.m for type details
141+ {
142+ import_function_t func{};
143+
144+ // [TODO] Create mechanism to generated type signatures
145+ func.sig = 0x4244b354;
146+
147+ std::array<uint8_t, 5> func_name = { "init" };
148+ func.name = std::make_unique<vm_string_t>(func_name.size() - 1, func_name.data());
149+
150+ import_vm_module_t import{};
151+ import.functions.push_back(std::move(func));
152+
153+ e.import_section.push_back(std::move(import));
154+ }
155+
156+ return entry_module;
157+ }
158+}
159+
160+int main(int argc, char* argv[])
161+{
162+ disvm::vm_t vm;
163+
164+ // Ignore the process name
165+ auto entry = create_entry_module(vm, argc - 1, argv + 1);
166+
167+ vm.exec(std::move(entry));
168+
169+ vm.spin_sleep_till_idle(std::chrono::milliseconds(100));
170+
171+ return 0;
172+}
173+