Coverage Report

Created: 2018-07-03 15:31

/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
}