/home/travis/build/MoarVM/MoarVM/src/mast/driver.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include "moar.h" |
2 | | #include "nodes.h" |
3 | | #include "compiler.h" |
4 | | |
5 | | /* Takes a hash of types and produces a MASTNodeTypes structure. */ |
6 | | #define grab_type(name) do { \ |
7 | | MVMString *key = MVM_string_utf8_decode(tc, tc->instance->VMString, #name, strlen(#name)); \ |
8 | | result->name = MVM_repr_at_key_o(tc, types, key); \ |
9 | | } while (0) |
10 | | |
11 | 1.21k | static MASTNodeTypes * node_types_struct(MVMThreadContext *tc, MVMObject *types) { |
12 | 1.21k | MASTNodeTypes *result = MVM_malloc(sizeof(MASTNodeTypes)); |
13 | 1.21k | MVMROOT(tc, types, { |
14 | 1.21k | grab_type(CompUnit); |
15 | 1.21k | grab_type(Frame); |
16 | 1.21k | grab_type(Op); |
17 | 1.21k | grab_type(ExtOp); |
18 | 1.21k | grab_type(SVal); |
19 | 1.21k | grab_type(IVal); |
20 | 1.21k | grab_type(NVal); |
21 | 1.21k | grab_type(Label); |
22 | 1.21k | grab_type(Local); |
23 | 1.21k | grab_type(Lexical); |
24 | 1.21k | grab_type(Call); |
25 | 1.21k | grab_type(Annotated); |
26 | 1.21k | grab_type(HandlerScope); |
27 | 1.21k | }); |
28 | 1.21k | return result; |
29 | 1.21k | } |
30 | | |
31 | | /* Compiles MAST down to bytecode, then loads it as a compilation unit, |
32 | | * running deserialize and load frames as appropriate. */ |
33 | | void MVM_mast_to_cu(MVMThreadContext *tc, MVMObject *mast, MVMObject *types, |
34 | 1.21k | MVMRegister *res) { |
35 | 1.21k | MVMCompUnit *loaded; |
36 | 1.21k | |
37 | 1.21k | MVMROOT(tc, mast, { |
38 | 1.21k | /* Get node types into struct. */ |
39 | 1.21k | MASTNodeTypes *mnt = node_types_struct(tc, types); |
40 | 1.21k | |
41 | 1.21k | /* Turn the MAST tree into bytecode. Switch to gen2 GC allocation to be |
42 | 1.21k | * sure nothing moves, though we'd really rather not have compiler |
43 | 1.21k | * temporaries live longer. */ |
44 | 1.21k | unsigned int size; |
45 | 1.21k | char *bytecode; |
46 | 1.21k | MVM_gc_allocate_gen2_default_set(tc); |
47 | 1.21k | bytecode = MVM_mast_compile(tc, mast, mnt, &size); |
48 | 1.21k | MVM_free(mnt); |
49 | 1.21k | MVM_gc_allocate_gen2_default_clear(tc); |
50 | 1.21k | |
51 | 1.21k | /* Load it as a compilation unit; it is a kind of MVMObject, so cast |
52 | 1.21k | * it to that. */ |
53 | 1.21k | loaded = MVM_cu_from_bytes(tc, (MVMuint8 *)bytecode, (MVMuint32)size); |
54 | 1.21k | loaded->body.deallocate = MVM_DEALLOCATE_FREE; |
55 | 1.21k | }); |
56 | 1.21k | |
57 | 1.21k | /* Stash loaded comp unit in result register. */ |
58 | 1.21k | res->o = (MVMObject *)loaded; |
59 | 1.21k | |
60 | 1.21k | /* If there's a deserialization frame, need to run that. */ |
61 | 1.21k | if (loaded->body.deserialize_frame) { |
62 | 1.08k | /* Set up special return to delegate to running the load frame, |
63 | 1.08k | * if any. */ |
64 | 1.08k | tc->cur_frame->return_value = NULL; |
65 | 1.08k | tc->cur_frame->return_type = MVM_RETURN_VOID; |
66 | 1.08k | |
67 | 1.08k | /* Invoke the deserialization frame and return to the runloop. */ |
68 | 1.08k | MVM_frame_invoke(tc, loaded->body.deserialize_frame, MVM_callsite_get_common(tc, MVM_CALLSITE_ID_NULL_ARGS), |
69 | 1.08k | NULL, NULL, NULL, -1); |
70 | 1.08k | } |
71 | 1.21k | } |
72 | | |
73 | | /* Compiles MAST down to bytecode, then writes it to disk. */ |
74 | 0 | void MVM_mast_to_file(MVMThreadContext *tc, MVMObject *mast, MVMObject *types, MVMString *filename) { |
75 | 0 | MVMROOT(tc, mast, { |
76 | 0 | FILE *fh; |
77 | 0 | char *c_filename; |
78 | 0 |
|
79 | 0 | /* Get node types into struct. */ |
80 | 0 | MASTNodeTypes *mnt = node_types_struct(tc, types); |
81 | 0 |
|
82 | 0 | /* Turn the MAST tree into bytecode. */ |
83 | 0 | unsigned int size; |
84 | 0 | char *bytecode; |
85 | 0 | MVM_gc_allocate_gen2_default_set(tc); |
86 | 0 | bytecode = MVM_mast_compile(tc, mast, mnt, &size); |
87 | 0 | MVM_free(mnt); |
88 | 0 | MVM_gc_allocate_gen2_default_clear(tc); |
89 | 0 |
|
90 | 0 | /* Write it out to a file. (Not using VM-level IO for this right now; |
91 | 0 | * may want to do that in the future.) */ |
92 | 0 | c_filename = MVM_string_utf8_c8_encode_C_string(tc, filename); |
93 | 0 | if ((fh = fopen(c_filename, "wb+"))) { |
94 | 0 | fwrite(bytecode, 1, size, fh); |
95 | 0 | fclose(fh); |
96 | 0 | MVM_free(c_filename); |
97 | 0 | MVM_free(bytecode); |
98 | 0 | } |
99 | 0 | else { |
100 | 0 | char *waste[2]; |
101 | 0 | waste[0] = c_filename; |
102 | 0 | waste[1] = NULL; |
103 | 0 | MVM_free(bytecode); |
104 | 0 | MVM_exception_throw_adhoc_free(tc, waste, "Unable to write bytecode to '%s'", c_filename); |
105 | 0 | } |
106 | 0 | }); |
107 | 0 | } |