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
14using namespace disvm;
15using namespace disvm::runtime;
16
17namespace
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
160int 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