Coverage Report

Created: 2017-04-15 07:07

/home/travis/build/MoarVM/MoarVM/src/main.c
Line
Count
Source (jump to first uncovered line)
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <string.h>
4
#include <moar.h>
5
6
#if MVM_TRACING
7
#  define TRACING_OPT "[--tracing] "
8
#  define TRACING_USAGE "\n    --tracing  output a line to stderr on every interpreter instr"
9
#else
10
#  define TRACING_OPT ""
11
#  define TRACING_USAGE ""
12
#endif
13
14
#ifndef _WIN32
15
#  include "signal.h"
16
#endif
17
18
/* flags need to be sorted alphabetically */
19
20
enum {
21
    NOT_A_FLAG = -2,
22
    UNKNOWN_FLAG = -1,
23
24
    FLAG_CRASH,
25
    FLAG_DUMP,
26
    FLAG_FULL_CLEANUP,
27
    FLAG_HELP,
28
    FLAG_TRACING,
29
    FLAG_VERSION,
30
31
    OPT_EXECNAME,
32
    OPT_LIBPATH
33
};
34
35
static const char *const FLAGS[] = {
36
    "--crash",
37
    "--dump",
38
    "--full-cleanup",
39
    "--help",
40
    "--tracing",
41
    "--version",
42
};
43
44
static const char USAGE[] = "\
45
USAGE: moar [--crash] [--libpath=...] " TRACING_OPT "input.moarvm [program args]\n\
46
       moar --dump input.moarvm\n\
47
       moar --help\n\
48
\n\
49
    --help            display this message\n\
50
    --dump            dump the bytecode to stdout instead of executing\n\
51
    --full-cleanup    try to free all memory and exit cleanly\n\
52
    --crash           abort instead of exiting on unhandled exception\n\
53
    --libpath         specify path loadbytecode should search in\n\
54
    --version         show version information"
55
    TRACING_USAGE
56
    "\n\
57
\n\
58
The following environment variables are respected:\n\
59
\n\
60
    MVM_SPESH_DISABLE           Disables all dynamic optimization\n\
61
    MVM_SPESH_NODELAY           Run dynamic optimization even for cold frames\n\
62
    MVM_SPESH_INLINE_DISABLE    Disables inlining\n\
63
    MVM_SPESH_OSR_DISABLE       Disables on-stack replacement\n\
64
    MVM_SPESH_LIMIT             Limit the maximum number of specializations\n\
65
    MVM_JIT_DISABLE             Disables JITting to machine code\n\
66
    MVM_SPESH_LOG               Specifies a dynamic optimizer log file\n\
67
    MVM_JIT_LOG                 Specifies a JIT-compiler log file\n\
68
    MVM_JIT_BYTECODE_DIR        Specifies a directory for JIT bytecode dumps\n\
69
    MVM_CROSS_THREAD_WRITE_LOG  Log unprotected cross-thread object writes to stderr\n\
70
    MVM_COVERAGE_LOG            Append line-by-line coverage messages to this file\n\
71
";
72
73
static int cmp_flag(const void *key, const void *value)
74
0
{
75
0
    return strcmp(key, *(char **)value);
76
0
}
77
78
0
static int starts_with(const char *str, const char *want) {
79
0
    size_t str_len  = strlen(str);
80
0
    size_t want_len = strlen(want);
81
0
    return str_len < want_len
82
0
        ? 0
83
0
        : strncmp(str, want, want_len) == 0;
84
0
}
85
86
static int parse_flag(const char *arg)
87
130
{
88
130
    const char *const *found;
89
130
90
130
    if (!arg || arg[0] != '-')
91
130
        return NOT_A_FLAG;
92
130
93
0
    found = bsearch(arg, FLAGS, sizeof FLAGS / sizeof *FLAGS, sizeof *FLAGS, cmp_flag);
94
0
95
0
    if (found)
96
0
        return (int)(found - FLAGS);
97
0
    else if (starts_with(arg, "--libpath="))
98
0
        return OPT_LIBPATH;
99
0
    else if (starts_with(arg, "--execname="))
100
0
        return OPT_EXECNAME;
101
0
    else
102
0
        return UNKNOWN_FLAG;
103
0
}
104
105
#ifndef _WIN32
106
int main(int argc, char *argv[])
107
#else
108
int wmain(int argc, wchar_t *wargv[])
109
#endif
110
130
{
111
130
    MVMInstance *instance;
112
130
    const char  *input_file;
113
130
    const char  *executable_name = NULL;
114
130
    const char  *lib_path[8];
115
130
116
130
#ifdef _WIN32
117
    char **argv = MVM_UnicodeToUTF8_argv(argc, wargv);
118
#endif
119
130
120
130
    int dump         = 0;
121
130
    int full_cleanup = 0;
122
130
    int argi         = 1;
123
130
    int lib_path_i   = 0;
124
130
    int flag;
125
130
126
130
    for (; (flag = parse_flag(argv[argi])) != NOT_A_FLAG; ++argi) {
127
0
        switch (flag) {
128
0
            case FLAG_CRASH:
129
0
            MVM_crash_on_error();
130
0
            continue;
131
0
132
0
            case FLAG_DUMP:
133
0
            dump = 1;
134
0
            continue;
135
0
136
0
            case FLAG_FULL_CLEANUP:
137
0
            full_cleanup = 1;
138
0
            continue;
139
0
140
0
            case FLAG_HELP:
141
0
            puts(USAGE);
142
0
            return EXIT_SUCCESS;
143
0
144
0
#if MVM_TRACING
145
            case FLAG_TRACING:
146
            MVM_interp_enable_tracing();
147
            continue;
148
#endif
149
0
150
0
            case OPT_EXECNAME:
151
0
            executable_name = argv[argi] + strlen("--execname=");
152
0
            continue;
153
0
154
0
            case OPT_LIBPATH:
155
0
            if (lib_path_i == 7) { /* 0..7 == 8 */
156
0
                fprintf(stderr, "ERROR: Only up to eight --libpath options are allowed.\n");
157
0
                return EXIT_FAILURE;
158
0
            }
159
0
160
0
            lib_path[lib_path_i++] = argv[argi] + strlen("--libpath=");
161
0
            continue;
162
0
163
0
            case FLAG_VERSION: {
164
0
            char *spesh_disable;
165
0
            char *jit_disable;
166
0
167
0
            printf("This is MoarVM version %s", MVM_VERSION);
168
0
            if (MVM_jit_support()) {
169
0
                printf(" built with JIT support");
170
0
171
0
                spesh_disable = getenv("MVM_SPESH_DISABLE");
172
0
                jit_disable = getenv("MVM_JIT_DISABLE");
173
0
                if (spesh_disable && strlen(spesh_disable) != 0) {
174
0
                    printf(" (disabled via MVM_SPESH_DISABLE)");
175
0
                } else if (jit_disable && strlen(jit_disable) != 0) {
176
0
                    printf(" (disabled via MVM_JIT_DISABLE)");
177
0
                }
178
0
            }
179
0
            printf("\n");
180
0
            return EXIT_SUCCESS;
181
0
            }
182
0
183
0
            default:
184
0
            fprintf(stderr, "ERROR: Unknown flag %s.\n\n%s\n", argv[argi], USAGE);
185
0
            return EXIT_FAILURE;
186
0
        }
187
0
    }
188
130
189
130
    lib_path[lib_path_i] = NULL;
190
130
191
130
    if (argi >= argc) {
192
0
        fprintf(stderr, "ERROR: Missing input file.\n\n%s\n", USAGE);
193
0
        return EXIT_FAILURE;
194
0
    }
195
130
196
130
    instance   = MVM_vm_create_instance();
197
130
    input_file = argv[argi++];
198
130
199
130
    /* stash the rest of the raw command line args in the instance */
200
130
    MVM_vm_set_clargs(instance, argc - argi, argv + argi);
201
130
    MVM_vm_set_prog_name(instance, input_file);
202
130
    MVM_vm_set_exec_name(instance, executable_name);
203
130
    MVM_vm_set_lib_path(instance, lib_path_i, lib_path);
204
130
205
130
    /* Ignore SIGPIPE by default, since we error-check reads/writes. This does
206
130
     * not prevent users from setting up their own signal handler for SIGPIPE,
207
130
     * which will take precedence over this ignore. */
208
130
#ifndef _WIN32
209
130
    signal(SIGPIPE, SIG_IGN);
210
130
#endif
211
130
212
130
    if (dump) MVM_vm_dump_file(instance, input_file);
213
130
    else MVM_vm_run_file(instance, input_file);
214
130
215
130
    if (full_cleanup) {
216
0
        MVM_vm_destroy_instance(instance);
217
0
        return EXIT_SUCCESS;
218
0
    }
219
130
    else {
220
130
        MVM_vm_exit(instance);
221
130
    }
222
130
}