1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
(** {0 OCaml compiler compatible command-line parameters} *)
let cmi_file = ref None
let include_dirs = ref []
let hidden_include_dirs = ref []
let fast = ref false
let classic = ref false
let all_ppx = ref []
let principal = ref false
let real_paths = ref true
let recursive_types = ref false
let strict_sequence = ref false
let applicative_functors = ref true
let nopervasives = ref false
let strict_formats = ref true
let open_modules = ref []
let annotations = ref false
let binary_annotations = ref true
let store_occurrences = ref true
let print_types = ref false
let native_code = ref false
let error_size = ref 500
let dont_write_files = ref true
let keep_locs = ref true
let keep_docs = ref false
let transparent_modules = ref true
let for_package = ref None
let debug = ref false
let unsafe = ref false
let opaque = ref false
let unboxed_types = ref false
let locations = ref true
let keyword_edition: string option ref = ref None
module Compiler_ir = struct
type t = Linear
let all = [
Linear;
]
let extension t =
let ext =
match t with
| Linear -> "linear"
in
".cmir-" ^ ext
(** [extract_extension_with_pass filename] returns the IR whose extension
is a prefix of the extension of [filename], and the suffix,
which can be used to distinguish different passes on the same IR.
For example, [extract_extension_with_pass "foo.cmir-linear123"]
returns [Some (Linear, "123")]. *)
let filename =
let ext = Filename.extension filename in
let ext_len = String.length ext in
if ext_len <= 0 then None
else begin
let is_prefix ir =
let s = extension ir in
let s_len = String.length s in
s_len <= ext_len && s = String.sub ext 0 s_len
in
let drop_prefix ir =
let s = extension ir in
let s_len = String.length s in
String.sub ext s_len (ext_len - s_len)
in
let ir = List.find_opt is_prefix all in
match ir with
| None -> None
| Some ir -> Some (ir, drop_prefix ir)
end
end
module Compiler_pass = struct
type t = Parsing | Typing | Lambda | Scheduling | Emit
let to_string = function
| Parsing -> "parsing"
| Typing -> "typing"
| Lambda -> "lambda"
| Scheduling -> "scheduling"
| Emit -> "emit"
let of_string = function
| "parsing" -> Some Parsing
| "typing" -> Some Typing
| "lambda" -> Some Lambda
| "scheduling" -> Some Scheduling
| "emit" -> Some Emit
| _ -> None
let rank = function
| Parsing -> 0
| Typing -> 1
| Lambda -> 2
| Scheduling -> 50
| Emit -> 60
let passes = [
Parsing;
Typing;
Lambda;
Scheduling;
Emit;
]
let is_compilation_pass _ = true
let is_native_only = function
| Scheduling -> true
| Emit -> true
| _ -> false
let enabled is_native t = not (is_native_only t) || is_native
let can_save_ir_after = function
| Scheduling -> true
| _ -> false
let available_pass_names ~filter ~native =
passes
|> List.filter (enabled native)
|> List.filter filter
|> List.map to_string
let compare a b =
compare (rank a) (rank b)
let to_output_filename t ~prefix =
match t with
| Scheduling -> prefix ^ Compiler_ir.(extension Linear)
| _ -> Misc.fatal_error "Not supported"
let of_input_filename name =
match Compiler_ir.extract_extension_with_pass name with
| Some (Linear, _) -> Some Emit
| None -> None
end
let parse_keyword_edition s =
let parse_version s =
let bad_version () =
raise (Arg.Bad "Ill-formed version in keywords flag,\n\
the supported format is <major>.<minor>, for example 5.2 .")
in
if s = "" then None else match String.split_on_char '.' s with
| [] | [_] | _ :: _ :: _ :: _ -> bad_version ()
| [major;minor] -> match int_of_string_opt major, int_of_string_opt minor with
| Some major, Some minor -> Some (major,minor)
| _ -> bad_version ()
in
match String.split_on_char '+' s with
| [] -> None, []
| [s] -> parse_version s, []
| v :: rest -> parse_version v, rest
let stop_after = ref None