History

Address code analysis violations. Disable all Microsoft language extensions - All header files now end with a single new line character. Split vs_asm header from type signature templates - vs_asm_sigkind.h created

arr committed 9 years ago

Commit 02a7d6a1 parent ea995f224 files · +417 −392Browse files

Unified · Split

24 files
  1. src/asm/type_signature.cpp +1 −1
  2. src/compiler_settings.gypi +2 −0
  3. src/exec/main.cpp +19 −23
  4. src/include/buffered_reader.h +1 −1
  5. src/include/builtin_module.h +1 −1
  6. src/include/debug.h +1 −1
  7. src/include/disvm.h +1 −1
  8. src/include/exceptions.h +1 −1
  9. src/include/module_reader.h +1 −1
  10. src/include/opcodes.h +1 −1
  11. src/include/utf8.h +1 −1
  12. src/include/utils.h +1 −1
  13. src/include/vm_asm.h +1 −346
  14. src/include/vm_asm_sigkind.h +366 −0
  15. src/include/vm_memory.h +1 −1
  16. src/include/vm_tools.h +1 −1
  17. src/include/vm_version.h +1 −1
  18. src/vm/execution_table.cpp +2 −2
  19. src/vm/execution_table.h +1 −1
  20. src/vm/garbage_collector.h +1 −1
  21. src/vm/scheduler.h +1 −1
  22. src/vm/sys/Sysmod.h +1 −1
  23. src/vm/thread.cpp +9 −3
  24. src/vm/tool_dispatch.h +1 −1
src/asm/type_signature.cpp+1−1
@@ -4,8 +4,8 @@ · 3 unmodified lines
44 // Author: arr
55 //
66
7−#include <vm_asm.h>
87 #include <array>
8+#include <vm_asm_sigkind.h>
99 #include "rfc1321/global.h"
1010 #include "rfc1321/md5.h"
1111
src/compiler_settings.gypi+2−0
@@ -33,6 +33,8 @@ · 32 unmodified lines
3333 },
3434 'msvs_settings': {
3535 'VCCLCompilerTool': {
36+ 'AdditionalOptions': '/Zc:rvalueCast',
37+ 'DisableLanguageExtensions': 'true',
3638 'TreatWChar_tAsBuiltInType': 'false',
3739 'WarningLevel': 3,
3840 'DebugInformationFormat': '3', # PDB
src/exec/main.cpp+19−23
@@ -11,7 +11,7 @@ · 10 unmodified lines
1111 #include <builtin_module.h>
1212 #include <debug.h>
1313 #include <exceptions.h>
14−#include <vm_asm.h>
14+#include <vm_asm_sigkind.h>
1515 #include <vm_version.h>
1616 #include "exec.h"
1717
@@ -21,6 +21,12 @@ using namespace disvm::assembly::sigkind; · 3 unmodified lines
2121
2222 namespace
2323 {
24+ template<int L>
25+ std::unique_ptr<vm_string_t> create_string_from_const(const char(&ca)[L])
26+ {
27+ return std::make_unique<vm_string_t>(L - 1, reinterpret_cast<const uint8_t*>(ca));
28+ }
29+
2430 // Entry frame layout
2531 struct vm_entry_frame_t final : public vm_frame_base_alloc_t
2632 {
@@ -35,24 +41,17 @@ namespace · 8 unmodified lines
3541
3642 std::unique_ptr<vm_module_t> create_entry_module(vm_t &vm, const std::vector<char *> &vm_args)
3743 {
38− if (vm_args.size() == 0)
39− throw vm_user_exception{ "Entry module not supplied" };
40−
4144 // Convert arguments to a list
4245 vm_string_t *command_module_path = nullptr;
43− vm_list_t *args = nullptr;
44− vm_list_t *last = nullptr;
45− for (auto i = std::size_t{ 0 }; i < vm_args.size(); ++i)
46+ vm_list_t *mod_args = new vm_list_t{ intrinsic_type_desc::type<vm_string_t>() };
47+ vm_list_t *last = mod_args;
48+ for (auto raw_arg : vm_args)
4649 {
47− auto tmp = vm_args[i];
48− auto arg = new vm_string_t{ std::strlen(tmp), reinterpret_cast<uint8_t *>(tmp) };
49− if (args == nullptr)
50+ auto curr_arg = new vm_string_t{ std::strlen(raw_arg), reinterpret_cast<uint8_t *>(raw_arg) };
51+ if (command_module_path == nullptr)
5052 {
5153 // First argument is the module to load
52− command_module_path = arg;
53− assert(last == nullptr);
54− args = new vm_list_t{ intrinsic_type_desc::type<vm_string_t>() };
55− last = args;
54+ command_module_path = curr_arg;
5655 }
5756 else
5857 {
@@ -63,10 +62,11 @@ namespace · 4 unmodified lines
6362 last = new_tail;
6463 }
6564
66− pt_ref(last->value()) = arg->get_allocation();
65+ pt_ref(last->value()) = curr_arg->get_allocation();
6766 }
6867
69− assert(args != nullptr);
68+ if (command_module_path == nullptr)
69+ throw vm_user_exception{ "Entry module not supplied" };
7070
7171 // Pre-load the command module in the VM.
7272 command_module = vm.load_module(command_module_path->str());
@@ -79,9 +79,7 @@ namespace · 6 unmodified lines
7979 e.header.entry_pc = 0;
8080 e.header.entry_type = 0;
8181 e.header.runtime_flag = (runtime_flags_t::has_import);
82−
83− std::array<uint8_t, 8> mod_name = { "_entry_" };
84− e.module_name = std::make_unique<vm_string_t>(mod_name.size() - 1, mod_name.data());
82+ e.module_name = create_string_from_const("_entry_");
8583
8684 // Inherit the stack extent from the command module and add the entry frame size.
8785 e.header.stack_extent = command_module->header.stack_extent + sizeof(vm_entry_frame_t);
@@ -99,7 +97,7 @@ namespace · 11 unmodified lines
9997 // Take a reference on the command module path and store it on the entry frame
10098 command_module_path->add_ref();
10199 mp_base[0] = command_module_path->get_allocation();
102− mp_base[1] = args->get_allocation();
100+ mp_base[1] = mod_args->get_allocation();
103101
104102 // Define the frame offset for the argument
105103 const auto first_arg_offset = vm_frame_constants::limbo_first_arg_register_offset();
@@ -168,9 +166,7 @@ namespace · 62 unmodified lines
168166 assert(exec_init_sig == sig_stream_t::compute_signature_hash("f(Ls)n"));
169167 #endif
170168 func.sig = exec_init_sig;
171−
172− std::array<uint8_t, 5> func_name = { "init" };
173− func.name = std::make_unique<vm_string_t>(func_name.size() - 1, func_name.data());
169+ func.name = create_string_from_const("init");
174170
175171 import_vm_module_t import{};
176172 import.functions.push_back(std::move(func));
src/include/buffered_reader.h+1−1
@@ -156,4 +156,4 @@ namespace disvm · 155 unmodified lines
156156 }
157157 }
158158
159−#endif // _DISVM_SRC_INCLUDE_BUFFERED_READER_H_
159+#endif // _DISVM_SRC_INCLUDE_BUFFERED_READER_H_
src/include/builtin_module.h+1−1
@@ -118,4 +118,4 @@ namespace disvm · 117 unmodified lines
118118 }
119119 }
120120
121−#endif // _DISVM_SRC_INCLUDE_BUILTIN_MODULE_H_
121+#endif // _DISVM_SRC_INCLUDE_BUILTIN_MODULE_H_
src/include/debug.h+1−1
@@ -97,4 +97,4 @@ namespace disvm · 96 unmodified lines
9797 }
9898 }
9999
100−#endif // _DISVM_SRC_INCLUDE_DEBUG_H_
100+#endif // _DISVM_SRC_INCLUDE_DEBUG_H_
src/include/disvm.h+1−1
@@ -125,4 +125,4 @@ namespace disvm · 124 unmodified lines
125125 };
126126 }
127127
128−#endif // _DISVM_SRC_INCLUDE_DISVM_H_
128+#endif // _DISVM_SRC_INCLUDE_DISVM_H_
src/include/exceptions.h+1−1
@@ -143,4 +143,4 @@ namespace disvm · 142 unmodified lines
143143 }
144144 }
145145
146−#endif // _DISVM_SRC_INCLUDE_EXCEPTIONS_H_
146+#endif // _DISVM_SRC_INCLUDE_EXCEPTIONS_H_
src/include/module_reader.h+1−1
@@ -26,4 +26,4 @@ namespace disvm · 25 unmodified lines
2626 }
2727 }
2828
29−#endif // _DISVM_SRC_INCLUDE_MODULE_READER_H_
29+#endif // _DISVM_SRC_INCLUDE_MODULE_READER_H_
src/include/opcodes.h+1−1
@@ -199,4 +199,4 @@ namespace disvm · 198 unmodified lines
199199 };
200200 }
201201
202−#endif // _DISVM_SRC_INCLUDE_OPCODES_H_
202+#endif // _DISVM_SRC_INCLUDE_OPCODES_H_
src/include/utf8.h+1−1
@@ -54,4 +54,4 @@ namespace disvm · 53 unmodified lines
5454 }
5555 }
5656
57−#endif // _DISVM_SRC_INCLUDE_UTF8_H_
57+#endif // _DISVM_SRC_INCLUDE_UTF8_H_
src/include/utils.h+1−1
@@ -78,4 +78,4 @@ inline TYPE operator ^ (TYPE a, TYPE b) { return static_cast<TYPE>(static_cast<s · 77 unmodified lines
7878 inline TYPE &operator ^= (TYPE &a, TYPE b) { a = a ^ b; return a; } \
7979 inline TYPE operator ~ (TYPE a) { return static_cast<TYPE>(~static_cast<std::underlying_type_t<TYPE>>(a)); }
8080
81−#endif // _DISVM_SRC_INCLUDE_UTILS_H_
81+#endif // _DISVM_SRC_INCLUDE_UTILS_H_
src/include/vm_asm.h+1−346
@@ -8,8 +8,6 @@ · 7 unmodified lines
88 #define _DISVM_SRC_INCLUDE_VM_ASM_H_
99
1010 #include <iosfwd>
11−#include <sstream>
12−#include <cassert>
1311 #include <cstdint>
1412 #include "opcodes.h"
1513 #include "runtime.h"
@@ -34,349 +32,6 @@ namespace disvm · 18 unmodified lines
3432 // Get the opcode from this string.
3533 // If the supplied string cannot be resolved or if it is null, the 'invalid' opcode is returned.
3634 disvm::opcode_t token_to_opcode(const char *);
37−
38− // Namespace named after enum type in Limbo compiler
39− // Source: limbo/types.c
40− namespace sigkind
41− {
42− // Signature stream
43− class sig_stream_t final
44− {
45− public: // static
46− static uint32_t compute_signature_hash(const char *);
47−
48− // Type delimiter
49− static const char delim;
50−
51− public:
52− std::string get_signature() const;
53−
54− uint32_t get_signature_hash() const;
55−
56− sig_stream_t &operator<<(const char);
57− sig_stream_t &operator<<(const char *);
58− sig_stream_t &operator<<(const uint32_t);
59− sig_stream_t &operator<<(const sig_stream_t &);
60−
61− private:
62− mutable std::stringstream _ss;
63− };
64−
65− // Type context modifiers
66− enum class modifier_id_t : uint8_t
67− {
68− self = 'S',
69− cycle = 'y',
70− };
71−
72− sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::modifier_id_t &);
73−
74− // Instrinsic VM types
75− enum class type_id_t : uint8_t
76− {
77− unknown = 0, // This will be interpreted as a 'null' value which will help debug where the type building failed.
78− none = 'n',
79− byte = 'b',
80− integer = 'i',
81− real = 'r',
82− big = 'B',
83− string = 's',
84− poly = 'P',
85− fixed = 'x',
86− array = 'A',
87− ref = 'R',
88− list = 'L',
89− channel = 'C',
90− adt = 'a',
91− adt_pick_tag = 'p',
92− tuple = 't',
93− module = 'm',
94− function = 'f',
95− function_varargs = 0xff, // "f*"
96− };
97−
98− sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::type_id_t &);
99−
100− template<type_id_t T>
101− struct Tbasic_type
102− {
103− static const type_id_t id;
104−
105− constexpr operator type_id_t() const
106− {
107− return Tbasic_type::id;
108− }
109− };
110−
111− template<type_id_t T>
112− const type_id_t Tbasic_type<T>::id = T;
113−
114− using Tnone = Tbasic_type<type_id_t::none>;
115− using Tbyte = Tbasic_type<type_id_t::byte>;
116− using Tinteger = Tbasic_type<type_id_t::integer>;
117− using Treal = Tbasic_type<type_id_t::real>;
118− using Tbig = Tbasic_type<type_id_t::big>;
119− using Tstring = Tbasic_type<type_id_t::string>;
120− using Tpoly = Tbasic_type<type_id_t::poly>;
121−
122− class Tfixed final : public Tbasic_type<type_id_t::fixed>
123− {
124− public:
125− Tfixed(double scale);
126−
127− friend sig_stream_t &operator<<(sig_stream_t &os, const Tfixed &);
128−
129− private:
130− const double _scale;
131− };
132−
133− sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tfixed &);
134−
135− // Type that contains/modifies another type
136− template <type_id_t ID>
137− class Tbasic_aggregate_type : public Tbasic_type<ID>
138− {
139− public:
140− template<typename U>
141− static Tbasic_aggregate_type create(const U &type)
142− {
143− sig_stream_t ss;
144− ss << Tbasic_type<ID>::id << type;
145−
146− return Tbasic_aggregate_type{ ss };
147− }
148−
149− friend sig_stream_t &operator<<(sig_stream_t &, const Tbasic_aggregate_type &);
150−
151− private:
152− sig_stream_t _s;
153− Tbasic_aggregate_type(sig_stream_t &s) : _s{ std::move(s) } { }
154− };
155−
156− using Tarray = Tbasic_aggregate_type<type_id_t::array>;
157− using Tref = Tbasic_aggregate_type<type_id_t::ref>;
158− using Tlist = Tbasic_aggregate_type<type_id_t::list>;
159− using Tchannel = Tbasic_aggregate_type<type_id_t::channel>;
160−
161− sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tarray &);
162− sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tref &);
163− sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tlist &);
164− sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tchannel &);
165−
166− // Reference to another previously defined type in the current signature
167− class Ttype_ref final
168− {
169− public: // static
170− static const char id;
171−
172− public:
173− Ttype_ref(uint32_t num);
174−
175− friend sig_stream_t &operator<<(sig_stream_t &os, const Ttype_ref &);
176−
177− private:
178− const uint32_t _num;
179− };
180−
181− sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Ttype_ref &);
182−
183− // Named member type
184− class Tm final
185− {
186− public:
187− template <typename T>
188− Tm(const char *name, const T &type)
189− {
190− _s << name << ':' << type;
191− }
192−
193− friend sig_stream_t &operator<<(sig_stream_t &os, const Tm &);
194−
195− private:
196− sig_stream_t _s;
197− };
198−
199− sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tm &);
200−
201− inline void nested_type(const sig_stream_t &)
202− {
203− return;
204− }
205−
206− template<typename T, typename ...S>
207− void nested_type(sig_stream_t &ss, const T &t, const S&...s)
208− {
209− ss << t;
210− nested_type(ss, s...);
211− }
212−
213− template<typename T1, typename T2, typename ...S>
214− void nested_type(sig_stream_t &ss, const T1 &t1, const T2 &t2, const S&...s)
215− {
216− ss << t1 << sig_stream_t::delim;
217− nested_type(ss, t2, s...);
218− }
219−
220− // Type whose definition depends on contained types
221− template <type_id_t ID>
222− class Tnested_aggregate_type : public Tbasic_type<ID>
223− {
224− public: // static
225− static const char begin;
226− static const char end;
227−
228− template<typename ...NT>
229− static Tnested_aggregate_type create(const NT&... nestedTypes)
230− {
231− sig_stream_t ss;
232− ss << Tbasic_type<ID>::id << Tnested_aggregate_type::begin;
233−
234− nested_type(ss, nestedTypes...);
235−
236− ss << Tnested_aggregate_type::end;
237−
238− return Tnested_aggregate_type{ ss };
239− }
240−
241− public:
242− Tnested_aggregate_type(sig_stream_t &s)
243− : _s{ std::move(s) }
244− { }
245−
246− friend sig_stream_t &operator<<(sig_stream_t &, const Tnested_aggregate_type &);
247−
248− private:
249− sig_stream_t _s;
250− };
251−
252− using Ttuple = Tnested_aggregate_type<type_id_t::tuple>;
253− using Tmodule = Tnested_aggregate_type<type_id_t::module>;
254−
255− sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Ttuple &);
256− sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tmodule &);
257−
258− // Abstract data type (ADT) pick tag
259− // Note: This type should only be a part of an ADT instance.
260− class Tadt_pick_tag final : public Tbasic_type<type_id_t::adt_pick_tag>
261− {
262− public: // static
263− static const char *tag_delim;
264− static const char begin;
265− static const char end;
266−
267− static Tadt_pick_tag create(const char *pick_tag, uint32_t adt_ref, std::initializer_list<const Tm> tms);
268−
269− friend sig_stream_t &operator<<(sig_stream_t &, const Tadt_pick_tag &);
270−
271− private:
272− sig_stream_t _s;
273− Tadt_pick_tag(sig_stream_t &s) : _s{ std::move(s) } { }
274− };
275−
276− sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tadt_pick_tag &);
277−
278− // Abstract data type (ADT)
279− class Tadt final : public Tnested_aggregate_type<type_id_t::adt>
280− {
281− public: // static
282− // Unhide base class version of function
283− using Tnested_aggregate_type::create;
284−
285− // Create an ADT with a single pick tag
286− static Tadt create(const Tadt_pick_tag &p)
287− {
288− sig_stream_t ss;
289− ss << Tbasic_type::id
290− << Tadt::begin
291− << sig_stream_t::delim
292− << p
293− << Tadt::end;
294−
295− return Tadt{ ss };
296− }
297−
298− template<typename T, typename ...NT>
299− static Tadt create(const Tadt_pick_tag &p, const T &t, const NT&... nestedTypes)
300− {
301− // [SPEC] When generating type signatures, the Limbo compiler
302− // doesn't identify the case where a pick tag is the first type
303− // so it always prefixes the nested signature with a leading ','.
304− // We special case this scenario to maintain compatibility. The
305− // single pick tag for an ADT must also be handled (above).
306− sig_stream_t ss;
307− ss << Tbasic_type::id
308− << Tadt::begin
309− << sig_stream_t::delim
310− << p
311− << sig_stream_t::delim;
312−
313− nested_type(ss, t, nestedTypes...);
314−
315− ss << Tadt::end;
316−
317− return Tadt{ ss };
318− }
319−
320− private:
321− Tadt(sig_stream_t &s) : Tnested_aggregate_type{ s } { }
322− };
323−
324− sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tnested_aggregate_type<type_id_t::adt> &);
325−
326− // Function type
327− template<type_id_t T>
328− class Tfunction_base_type final : public Tbasic_type<T>
329− {
330− public: // static
331− static const char begin;
332− static const char end;
333−
334− template<typename ...AT>
335− static Tfunction_base_type create(AT... argTypes)
336− {
337− Tfunction_base_type a;
338− a._s << Tfunction_base_type::id << Tfunction_base_type::begin;
339−
340− nested_type(a._s, argTypes...);
341−
342− a._s << Tfunction_base_type::end;
343− return a;
344− }
345−
346− public:
347− template<typename RT>
348− Tfunction_base_type &returns(RT r)
349− {
350− assert(!_fully_defined && "Function type already complete");
351− _s << r;
352− _fully_defined = true;
353−
354− return *this;
355− }
356−
357− friend sig_stream_t &operator<<(sig_stream_t &, Tfunction_base_type &);
358− friend sig_stream_t &operator<<(sig_stream_t &, const Tfunction_base_type &);
359−
360− private:
361− bool _fully_defined;
362− sig_stream_t _s;
363− Tfunction_base_type() : _fully_defined{ false } { }
364− };
365−
366− template<type_id_t T>
367− const char Tfunction_base_type<T>::begin = '(';
368−
369− template<type_id_t T>
370− const char Tfunction_base_type<T>::end = ')';
371−
372− using Tfunction = Tfunction_base_type<type_id_t::function>;
373− using Tfunction_varargs = Tfunction_base_type<type_id_t::function_varargs>;
374−
375− sig_stream_t &operator<<(sig_stream_t &, disvm::assembly::sigkind::Tfunction &);
376− sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tfunction &);
377− sig_stream_t &operator<<(sig_stream_t &, disvm::assembly::sigkind::Tfunction_varargs &);
378− sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tfunction_varargs &);
379− }
38035 }
38136
38237 namespace symbol
@@ -495,4 +150,4 @@ namespace disvm · 112 unmodified lines
495150 }
496151 }
497152
498−#endif // _DISVM_SRC_INCLUDE_VM_ASM_H_
153+#endif // _DISVM_SRC_INCLUDE_VM_ASM_H_
src/include/vm_asm_sigkind.h+366−0
@@ -0,0 +1,366 @@
1+//
2+// Dis VM
3+// File: vm_asm_sigkind.h
4+// Author: arr
5+//
6+
7+#ifndef _DISVM_SRC_INCLUDE_VM_ASM_SIGKIND_H_
8+#define _DISVM_SRC_INCLUDE_VM_ASM_SIGKIND_H_
9+
10+#include <iosfwd>
11+#include <sstream>
12+#include <cassert>
13+#include <cstdint>
14+#include "opcodes.h"
15+#include "runtime.h"
16+
17+namespace disvm
18+{
19+ namespace assembly
20+ {
21+ // Namespace named after enum type in Limbo compiler
22+ // Source: limbo/types.c
23+ namespace sigkind
24+ {
25+ // Signature stream
26+ class sig_stream_t final
27+ {
28+ public: // static
29+ static uint32_t compute_signature_hash(const char *);
30+
31+ // Type delimiter
32+ static const char delim;
33+
34+ public:
35+ std::string get_signature() const;
36+
37+ uint32_t get_signature_hash() const;
38+
39+ sig_stream_t &operator<<(const char);
40+ sig_stream_t &operator<<(const char *);
41+ sig_stream_t &operator<<(const uint32_t);
42+ sig_stream_t &operator<<(const sig_stream_t &);
43+
44+ private:
45+ mutable std::stringstream _ss;
46+ };
47+
48+ // Type context modifiers
49+ enum class modifier_id_t : uint8_t
50+ {
51+ self = 'S',
52+ cycle = 'y',
53+ };
54+
55+ sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::modifier_id_t &);
56+
57+ // Instrinsic VM types
58+ enum class type_id_t : uint8_t
59+ {
60+ unknown = 0, // This will be interpreted as a 'null' value which will help debug where the type building failed.
61+ none = 'n',
62+ byte = 'b',
63+ integer = 'i',
64+ real = 'r',
65+ big = 'B',
66+ string = 's',
67+ poly = 'P',
68+ fixed = 'x',
69+ array = 'A',
70+ ref = 'R',
71+ list = 'L',
72+ channel = 'C',
73+ adt = 'a',
74+ adt_pick_tag = 'p',
75+ tuple = 't',
76+ module = 'm',
77+ function = 'f',
78+ function_varargs = 0xff, // "f*"
79+ };
80+
81+ sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::type_id_t &);
82+
83+ template<type_id_t T>
84+ struct Tbasic_type
85+ {
86+ static const type_id_t id;
87+
88+ constexpr operator type_id_t() const
89+ {
90+ return Tbasic_type::id;
91+ }
92+ };
93+
94+ template<type_id_t T>
95+ const type_id_t Tbasic_type<T>::id = T;
96+
97+ using Tnone = Tbasic_type<type_id_t::none>;
98+ using Tbyte = Tbasic_type<type_id_t::byte>;
99+ using Tinteger = Tbasic_type<type_id_t::integer>;
100+ using Treal = Tbasic_type<type_id_t::real>;
101+ using Tbig = Tbasic_type<type_id_t::big>;
102+ using Tstring = Tbasic_type<type_id_t::string>;
103+ using Tpoly = Tbasic_type<type_id_t::poly>;
104+
105+ class Tfixed final : public Tbasic_type<type_id_t::fixed>
106+ {
107+ public:
108+ Tfixed(double scale);
109+
110+ friend sig_stream_t &operator<<(sig_stream_t &os, const Tfixed &);
111+
112+ private:
113+ const double _scale;
114+ };
115+
116+ sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tfixed &);
117+
118+ // Type that contains/modifies another type
119+ template <type_id_t ID>
120+ class Tbasic_aggregate_type : public Tbasic_type<ID>
121+ {
122+ public:
123+ template<typename U>
124+ static Tbasic_aggregate_type create(const U &type)
125+ {
126+ sig_stream_t ss;
127+ ss << Tbasic_type<ID>::id << type;
128+
129+ return Tbasic_aggregate_type{ ss };
130+ }
131+
132+ friend sig_stream_t &operator<<(sig_stream_t &, const Tbasic_aggregate_type &);
133+
134+ private:
135+ sig_stream_t _s;
136+ Tbasic_aggregate_type(sig_stream_t &s) : _s{ std::move(s) } { }
137+ };
138+
139+ using Tarray = Tbasic_aggregate_type<type_id_t::array>;
140+ using Tref = Tbasic_aggregate_type<type_id_t::ref>;
141+ using Tlist = Tbasic_aggregate_type<type_id_t::list>;
142+ using Tchannel = Tbasic_aggregate_type<type_id_t::channel>;
143+
144+ sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tarray &);
145+ sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tref &);
146+ sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tlist &);
147+ sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tchannel &);
148+
149+ // Reference to another previously defined type in the current signature
150+ class Ttype_ref final
151+ {
152+ public: // static
153+ static const char id;
154+
155+ public:
156+ Ttype_ref(uint32_t num);
157+
158+ friend sig_stream_t &operator<<(sig_stream_t &os, const Ttype_ref &);
159+
160+ private:
161+ const uint32_t _num;
162+ };
163+
164+ sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Ttype_ref &);
165+
166+ // Named member type
167+ class Tm final
168+ {
169+ public:
170+ template <typename T>
171+ Tm(const char *name, const T &type)
172+ {
173+ _s << name << ':' << type;
174+ }
175+
176+ friend sig_stream_t &operator<<(sig_stream_t &os, const Tm &);
177+
178+ private:
179+ sig_stream_t _s;
180+ };
181+
182+ sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tm &);
183+
184+ inline void nested_type(const sig_stream_t &)
185+ {
186+ return;
187+ }
188+
189+ template<typename T, typename ...S>
190+ void nested_type(sig_stream_t &ss, const T &t, const S&...s)
191+ {
192+ ss << t;
193+ nested_type(ss, s...);
194+ }
195+
196+ template<typename T1, typename T2, typename ...S>
197+ void nested_type(sig_stream_t &ss, const T1 &t1, const T2 &t2, const S&...s)
198+ {
199+ ss << t1 << sig_stream_t::delim;
200+ nested_type(ss, t2, s...);
201+ }
202+
203+ // Type whose definition depends on contained types
204+ template <type_id_t ID>
205+ class Tnested_aggregate_type : public Tbasic_type<ID>
206+ {
207+ public: // static
208+ static const char begin;
209+ static const char end;
210+
211+ template<typename ...NT>
212+ static Tnested_aggregate_type create(const NT&... nestedTypes)
213+ {
214+ sig_stream_t ss;
215+ ss << Tbasic_type<ID>::id << Tnested_aggregate_type::begin;
216+
217+ nested_type(ss, nestedTypes...);
218+
219+ ss << Tnested_aggregate_type::end;
220+
221+ return Tnested_aggregate_type{ ss };
222+ }
223+
224+ public:
225+ Tnested_aggregate_type(sig_stream_t &s)
226+ : _s{ std::move(s) }
227+ { }
228+
229+ friend sig_stream_t &operator<<(sig_stream_t &, const Tnested_aggregate_type &);
230+
231+ private:
232+ sig_stream_t _s;
233+ };
234+
235+ using Ttuple = Tnested_aggregate_type<type_id_t::tuple>;
236+ using Tmodule = Tnested_aggregate_type<type_id_t::module>;
237+
238+ sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Ttuple &);
239+ sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tmodule &);
240+
241+ // Abstract data type (ADT) pick tag
242+ // Note: This type should only be a part of an ADT instance.
243+ class Tadt_pick_tag final : public Tbasic_type<type_id_t::adt_pick_tag>
244+ {
245+ public: // static
246+ static const char *tag_delim;
247+ static const char begin;
248+ static const char end;
249+
250+ static Tadt_pick_tag create(const char *pick_tag, uint32_t adt_ref, std::initializer_list<const Tm> tms);
251+
252+ friend sig_stream_t &operator<<(sig_stream_t &, const Tadt_pick_tag &);
253+
254+ private:
255+ sig_stream_t _s;
256+ Tadt_pick_tag(sig_stream_t &s) : _s{ std::move(s) } { }
257+ };
258+
259+ sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tadt_pick_tag &);
260+
261+ // Abstract data type (ADT)
262+ class Tadt final : public Tnested_aggregate_type<type_id_t::adt>
263+ {
264+ public: // static
265+ // Unhide base class version of function
266+ using Tnested_aggregate_type::create;
267+
268+ // Create an ADT with a single pick tag
269+ static Tadt create(const Tadt_pick_tag &p)
270+ {
271+ sig_stream_t ss;
272+ ss << Tbasic_type::id
273+ << Tadt::begin
274+ << sig_stream_t::delim
275+ << p
276+ << Tadt::end;
277+
278+ return Tadt{ ss };
279+ }
280+
281+ template<typename T, typename ...NT>
282+ static Tadt create(const Tadt_pick_tag &p, const T &t, const NT&... nestedTypes)
283+ {
284+ // [SPEC] When generating type signatures, the Limbo compiler
285+ // doesn't identify the case where a pick tag is the first type
286+ // so it always prefixes the nested signature with a leading ','.
287+ // We special case this scenario to maintain compatibility. The
288+ // single pick tag for an ADT must also be handled (above).
289+ sig_stream_t ss;
290+ ss << Tbasic_type::id
291+ << Tadt::begin
292+ << sig_stream_t::delim
293+ << p
294+ << sig_stream_t::delim;
295+
296+ nested_type(ss, t, nestedTypes...);
297+
298+ ss << Tadt::end;
299+
300+ return Tadt{ ss };
301+ }
302+
303+ private:
304+ Tadt(sig_stream_t &s) : Tnested_aggregate_type{ s } { }
305+ };
306+
307+ sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tnested_aggregate_type<type_id_t::adt> &);
308+
309+ // Function type
310+ template<type_id_t T>
311+ class Tfunction_base_type final : public Tbasic_type<T>
312+ {
313+ public: // static
314+ static const char begin;
315+ static const char end;
316+
317+ template<typename ...AT>
318+ static Tfunction_base_type create(AT... argTypes)
319+ {
320+ Tfunction_base_type a;
321+ a._s << Tfunction_base_type::id << Tfunction_base_type::begin;
322+
323+ nested_type(a._s, argTypes...);
324+
325+ a._s << Tfunction_base_type::end;
326+ return a;
327+ }
328+
329+ public:
330+ template<typename RT>
331+ Tfunction_base_type &returns(RT r)
332+ {
333+ assert(!_fully_defined && "Function type already complete");
334+ _s << r;
335+ _fully_defined = true;
336+
337+ return *this;
338+ }
339+
340+ friend sig_stream_t &operator<<(sig_stream_t &, Tfunction_base_type &);
341+ friend sig_stream_t &operator<<(sig_stream_t &, const Tfunction_base_type &);
342+
343+ private:
344+ bool _fully_defined;
345+ sig_stream_t _s;
346+ Tfunction_base_type() : _fully_defined{ false } { }
347+ };
348+
349+ template<type_id_t T>
350+ const char Tfunction_base_type<T>::begin = '(';
351+
352+ template<type_id_t T>
353+ const char Tfunction_base_type<T>::end = ')';
354+
355+ using Tfunction = Tfunction_base_type<type_id_t::function>;
356+ using Tfunction_varargs = Tfunction_base_type<type_id_t::function_varargs>;
357+
358+ sig_stream_t &operator<<(sig_stream_t &, disvm::assembly::sigkind::Tfunction &);
359+ sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tfunction &);
360+ sig_stream_t &operator<<(sig_stream_t &, disvm::assembly::sigkind::Tfunction_varargs &);
361+ sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tfunction_varargs &);
362+ }
363+ }
364+}
365+
366+#endif // _DISVM_SRC_INCLUDE_VM_ASM_SIGKIND_H_
src/include/vm_memory.h+1−1
@@ -131,4 +131,4 @@ namespace disvm · 130 unmodified lines
131131 }
132132 }
133133
134−#endif // _DISVM_SRC_INCLUDE_VM_MEMORY_H_
134+#endif // _DISVM_SRC_INCLUDE_VM_MEMORY_H_
src/include/vm_tools.h+1−1
@@ -95,4 +95,4 @@ namespace disvm · 94 unmodified lines
9595 }
9696 }
9797
98−#endif // _DISVM_SRC_INCLUDE_VM_TOOLS_H_
98+#endif // _DISVM_SRC_INCLUDE_VM_TOOLS_H_
src/include/vm_version.h+1−1
@@ -12,4 +12,4 @@ · 11 unmodified lines
1212 #define DISVM_VERSION_PATCH 0
1313 #define DISVM_VERSION_LABEL "alpha"
1414
15−#endif // _DISVM_SRC_INCLUDE_VM_VERSION_H_
15+#endif // _DISVM_SRC_INCLUDE_VM_VERSION_H_
src/vm/execution_table.cpp+2−2
@@ -1678,7 +1678,7 @@ namespace · 1677 unmodified lines
16781678
16791679 assert(r.module_ref != nullptr);
16801680 std::tie(handler, target_frame, handler_pc) = find_exception_handler(r.stack, *r.module_ref, faulting_pc, *exception_id);
1681− if (handler == nullptr && target_frame == nullptr && handler_pc == runtime_constants::invalid_program_counter)
1681+ if (handler == nullptr)
16821682 {
16831683 if (tool_dispatch != nullptr)
16841684 tool_dispatch->on_exception_unhandled(r, *exception_id, *e);
@@ -1687,7 +1687,7 @@ namespace · 2 unmodified lines
16871687 throw unhandled_user_exception{ exception_id->str(), faulting_module_name, faulting_pc };
16881688 }
16891689
1690− assert(target_frame != nullptr);
1690+ assert(target_frame != nullptr && handler_pc != runtime_constants::invalid_program_counter);
16911691
16921692 // Now that we know the exception has a handler, take a reference.
16931693 e->add_ref();
src/vm/execution_table.h+1−1
@@ -18,4 +18,4 @@ namespace disvm · 17 unmodified lines
1818 }
1919 }
2020
21−#endif // _DISVM_SRC_VM_EXECUTION_TABLE_H_
21+#endif // _DISVM_SRC_VM_EXECUTION_TABLE_H_
src/vm/garbage_collector.h+1−1
@@ -42,4 +42,4 @@ namespace disvm · 41 unmodified lines
4242 }
4343 }
4444
45−#endif // _DISVM_SRC_VM_GARBAGE_COLLECTOR_H_
45+#endif // _DISVM_SRC_VM_GARBAGE_COLLECTOR_H_
src/vm/scheduler.h+1−1
@@ -102,4 +102,4 @@ namespace disvm · 101 unmodified lines
102102 }
103103 }
104104
105−#endif // _DISVM_SRC_VM_SCHEDULER_H_
105+#endif // _DISVM_SRC_VM_SCHEDULER_H_
src/vm/sys/Sysmod.h+1−1
@@ -461,4 +461,4 @@ const word_t Sys_UTFerror = 0xfffd; · 460 unmodified lines
461461 const word_t Sys_Runemax = 0x10ffff;
462462 const word_t Sys_Runemask = 0x1fffff;
463463
464−#endif // _DISVM_SRC_VM_SYS_SYSMOD_H_
464+#endif // _DISVM_SRC_VM_SYS_SYSMOD_H_
src/vm/thread.cpp+9−3
@@ -239,19 +239,25 @@ vm_thread_state_t vm_thread_t::execute(vm_t &vm, const uint32_t quanta) · 238 unmodified lines
239239 catch (const unhandled_user_exception &uue)
240240 {
241241 _error_message = calloc_memory<char>(max_error_message);
242− std::snprintf(_error_message, max_error_message, "%s - '%s' in %s at instruction %d", uue.what(), uue.exception_id, uue.module_name, uue.program_counter);
242+ const int ec = std::snprintf(_error_message, max_error_message, "%s - '%s' in %s at instruction %d", uue.what(), uue.exception_id, uue.module_name, uue.program_counter);
243+ assert(ec > 0 && ec < max_error_message);
244+ (void)ec;
243245 _registers.current_thread_state = vm_thread_state_t::broken;
244246 }
245247 catch (const index_out_of_range_memory &ioor)
246248 {
247249 _error_message = calloc_memory<char>(max_error_message);
248− std::snprintf(_error_message, max_error_message, "%s - %d [%d,%d]", ioor.what(), ioor.invalid_value, ioor.valid_min, ioor.valid_max);
250+ const int ec = std::snprintf(_error_message, max_error_message, "%s - %d [%d,%d]", ioor.what(), ioor.invalid_value, ioor.valid_min, ioor.valid_max);
251+ assert(ec > 0 && ec < max_error_message);
252+ (void)ec;
249253 _registers.current_thread_state = vm_thread_state_t::broken;
250254 }
251255 catch (const vm_user_exception &ue)
252256 {
253257 _error_message = calloc_memory<char>(max_error_message);
254− std::snprintf(_error_message, max_error_message, "%s", ue.what());
258+ const int ec = std::snprintf(_error_message, max_error_message, "%s", ue.what());
259+ assert(ec > 0 && ec < max_error_message);
260+ (void)ec;
255261 _registers.current_thread_state = vm_thread_state_t::broken;
256262 }
257263
src/vm/tool_dispatch.h+1−1
@@ -122,4 +122,4 @@ namespace disvm · 121 unmodified lines
122122 }
123123 }
124124
125−#endif // _DISVM_SRC_VM_TOOL_DISPATCH_H_
125+#endif // _DISVM_SRC_VM_TOOL_DISPATCH_H_