Skip to content

Commit 1a27c12

Browse files
authored
feat(compiler)!: Replace optimization levels with compilation profiles (#1270)
1 parent 96e8ecb commit 1a27c12

File tree

333 files changed

+44252
-31217
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

333 files changed

+44252
-31217
lines changed

cli/bin/grain.js

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -69,19 +69,34 @@ class ForwardOption extends program.Option {
6969
}
7070
}
7171

72+
class ProfileOption extends program.Option {
73+
// Like ForwardOption, ProfileOption is forwarded to the underlying program
74+
// but we convert the flag into a profile flag, i.e. `--release` becomes `--profile=release`
75+
forward = true;
76+
77+
toFlag(opts) {
78+
const attribute = this.attributeName();
79+
if (opts[attribute]) {
80+
return `--profile=${attribute}`;
81+
}
82+
}
83+
}
84+
85+
const optionApplicator = (Option) =>
86+
function (flags, description, parser, defaultValue) {
87+
const option = new Option(flags, description);
88+
if (parser) option.argParser(parser);
89+
if (typeof defaultValue !== "undefined") option.default(defaultValue);
90+
return this.addOption(option);
91+
};
92+
7293
// Adds .forwardOption to commands. Similar to Commander's native .option,
7394
// but will forward the flag to the underlying program.
74-
program.Command.prototype.forwardOption = function (
75-
flags,
76-
description,
77-
parser,
78-
defaultValue
79-
) {
80-
const option = new ForwardOption(flags, description);
81-
if (parser) option.argParser(parser);
82-
if (typeof defaultValue !== "undefined") option.default(defaultValue);
83-
return this.addOption(option);
84-
};
95+
program.Command.prototype.forwardOption = optionApplicator(ForwardOption);
96+
97+
// Adds .profileOption to commands. Similar to Commander's native .option,
98+
// but will convert the flag from the shorthand to the full form.
99+
program.Command.prototype.profileOption = optionApplicator(ProfileOption);
85100

86101
program
87102
.option("-v, --version", "output CLI and compiler versions")
@@ -123,6 +138,10 @@ program
123138
"--elide-type-info",
124139
"don't include runtime type information used by toString/print"
125140
)
141+
.profileOption(
142+
"--release",
143+
"compile using the release profile (production mode)"
144+
)
126145
.forwardOption(
127146
"--experimental-wasm-tail-call",
128147
"enables tail-call optimization"

compiler/src/codegen/compcore.re

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3866,11 +3866,9 @@ let compile_wasm_module = (~env=?, ~name=?, prog) => {
38663866
);
38673867
validate_module(~name?, wasm_mod);
38683868

3869-
switch (Config.optimization_level^) {
3870-
| Level_three => Optimize_mod.optimize(wasm_mod)
3871-
| Level_zero
3872-
| Level_one
3873-
| Level_two => ()
3869+
switch (Config.profile^) {
3870+
| Some(Release) => Optimize_mod.optimize(wasm_mod)
3871+
| None => ()
38743872
};
38753873
wasm_mod;
38763874
};

compiler/src/compile.re

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -159,13 +159,7 @@ let next_state = (~is_root_file=false, {cstate_desc, cstate_filename} as cs) =>
159159
TypedWellFormed(typed_mod);
160160
| TypedWellFormed(typed_mod) =>
161161
Linearized(Linearize.transl_anf_module(typed_mod))
162-
| Linearized(anfed) =>
163-
switch (Grain_utils.Config.optimization_level^) {
164-
| Level_one
165-
| Level_two
166-
| Level_three => Optimized(Optimize.optimize_program(anfed))
167-
| Level_zero => Optimized(anfed)
168-
}
162+
| Linearized(anfed) => Optimized(Optimize.optimize_program(anfed))
169163
| Optimized(optimized) =>
170164
Mashed(Transl_anf.transl_anf_program(optimized))
171165
| Mashed(mashed) =>

compiler/src/linking/link.re

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -611,11 +611,9 @@ let link_modules = ({asm: wasm_mod, signature}) => {
611611
if (Module.validate(linked_mod) != 1) {
612612
failwith("Generated invalid linked module");
613613
};
614-
switch (Config.optimization_level^) {
615-
| Level_three => Optimize_mod.optimize(linked_mod)
616-
| Level_zero
617-
| Level_one
618-
| Level_two => ()
614+
switch (Config.profile^) {
615+
| Some(Release) => Optimize_mod.optimize(linked_mod)
616+
| None => ()
619617
};
620618
linked_mod;
621619
};

compiler/src/utils/config.re

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -384,24 +384,15 @@ let option_conv = ((prsr, prntr)) => (
384384
| Some(x) => prntr(ppf, x),
385385
);
386386

387-
type optimization_level =
388-
| Level_zero
389-
| Level_one
390-
| Level_two
391-
| Level_three;
387+
type profile =
388+
| Release;
392389

393-
let optimization_level =
390+
let profile =
394391
opt(
395-
~doc="Set the optimization level.",
396-
~names=["O"],
397-
~conv=
398-
Cmdliner.Arg.enum([
399-
("0", Level_zero),
400-
("1", Level_one),
401-
("2", Level_two),
402-
("3", Level_three),
403-
]),
404-
Level_three,
392+
~doc="Set a compilation profile.",
393+
~names=["profile"],
394+
~conv=Cmdliner.Arg.enum([("release", Some(Release))]),
395+
None,
405396
);
406397

407398
let default_memory_base = 0x400;

compiler/src/utils/config.rei

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
type optimization_level =
2-
| Level_zero
3-
| Level_one
4-
| Level_two
5-
| Level_three;
1+
type profile =
2+
| Release;
63

74
/** The Grain stdlib directory, based on the current configuration */
85
let stdlib_directory: unit => option(string);
@@ -43,9 +40,9 @@ let wasi_polyfill: ref(option(string));
4340

4441
let use_start_section: ref(bool);
4542

46-
/** Whether optimizations should be run */
43+
/** Compilation profile, e.g. release for production builds */
4744

48-
let optimization_level: ref(optimization_level);
45+
let profile: ref(option(profile));
4946

5047
// [NOTE] This default is here because it is used in multiple locations,
5148
// and it doesn't make sense for it to be "owned" by any of them.

compiler/test/__snapshots__/arrays.0f9e7d37.0.snapshot

Lines changed: 130 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ arrays › array_access
44
(type $none_=>_i32 (func (result i32)))
55
(type $none_=>_none (func))
66
(import \"_grainEnv\" \"mem\" (memory $0 0))
7+
(import \"_grainEnv\" \"tbl\" (table $tbl 0 funcref))
78
(import \"_grainEnv\" \"relocBase\" (global $relocBase_0 i32))
9+
(import \"_grainEnv\" \"moduleRuntimeId\" (global $moduleRuntimeId_0 i32))
810
(import \"GRAIN$MODULE$runtime/exception\" \"GRAIN$EXPORT$printException\" (global $GRAIN$EXPORT$printException_0 (mut i32)))
911
(import \"GRAIN$MODULE$runtime/exception\" \"GRAIN$EXPORT$IndexOutOfBounds\" (global $GRAIN$EXPORT$IndexOutOfBounds_0 (mut i32)))
1012
(import \"GRAIN$MODULE$runtime/gc\" \"GRAIN$EXPORT$malloc\" (global $GRAIN$EXPORT$malloc_0 (mut i32)))
@@ -16,104 +18,147 @@ arrays › array_access
1618
(import \"GRAIN$MODULE$runtime/exception\" \"printException\" (func $printException_0 (param i32 i32) (result i32)))
1719
(global $x_1131 (mut i32) (i32.const 0))
1820
(global $GRAIN$TABLE_SIZE i32 (i32.const 0))
21+
(elem $elem (global.get $relocBase_0))
1922
(export \"memory\" (memory $0))
2023
(export \"_gmain\" (func $_gmain))
2124
(export \"_start\" (func $_start))
2225
(export \"GRAIN$TABLE_SIZE\" (global $GRAIN$TABLE_SIZE))
23-
(func $_gmain (; has Stack IR ;) (result i32)
26+
(func $_gmain (result i32)
2427
(local $0 i32)
2528
(local $1 i32)
26-
(i32.store
27-
(local.tee $0
28-
(call $malloc_0
29-
(global.get $GRAIN$EXPORT$malloc_0)
30-
(i32.const 20)
31-
)
32-
)
33-
(i32.const 4)
34-
)
35-
(i32.store offset=4
36-
(local.get $0)
37-
(i32.const 3)
38-
)
39-
(i32.store offset=8
40-
(local.get $0)
41-
(i32.const 3)
42-
)
43-
(i32.store offset=12
44-
(local.get $0)
45-
(i32.const 5)
46-
)
47-
(i32.store offset=16
48-
(local.get $0)
49-
(i32.const 7)
50-
)
51-
(global.set $x_1131
52-
(tuple.extract 0
53-
(tuple.make
54-
(local.get $0)
55-
(call $decRef_0
56-
(global.get $GRAIN$EXPORT$decRef_0)
57-
(global.get $x_1131)
58-
)
59-
)
60-
)
61-
)
62-
(if
63-
(i32.lt_s
64-
(local.tee $0
65-
(i32.const 0)
66-
)
67-
(i32.sub
68-
(i32.const 0)
69-
(i32.load offset=4
70-
(local.tee $1
71-
(global.get $x_1131)
29+
(local $2 i32)
30+
(local $3 i64)
31+
(local $4 f32)
32+
(local $5 f64)
33+
(return
34+
(block $cleanup_locals.8 (result i32)
35+
(local.set $0
36+
(block $compile_block.7 (result i32)
37+
(block $compile_store.3
38+
(global.set $x_1131
39+
(tuple.extract 0
40+
(tuple.make
41+
(block $allocate_array.1 (result i32)
42+
(i32.store
43+
(local.tee $0
44+
(call $malloc_0
45+
(global.get $GRAIN$EXPORT$malloc_0)
46+
(i32.const 20)
47+
)
48+
)
49+
(i32.const 4)
50+
)
51+
(i32.store offset=4
52+
(local.get $0)
53+
(i32.const 3)
54+
)
55+
(i32.store offset=8
56+
(local.get $0)
57+
(i32.const 3)
58+
)
59+
(i32.store offset=12
60+
(local.get $0)
61+
(i32.const 5)
62+
)
63+
(i32.store offset=16
64+
(local.get $0)
65+
(i32.const 7)
66+
)
67+
(local.get $0)
68+
)
69+
(call $decRef_0
70+
(global.get $GRAIN$EXPORT$decRef_0)
71+
(global.get $x_1131)
72+
)
73+
)
74+
)
75+
)
76+
(block $do_backpatches.2
77+
)
78+
)
79+
(block $MArrayGet.6 (result i32)
80+
(local.set $1
81+
(i32.shr_s
82+
(i32.const 1)
83+
(i32.const 1)
84+
)
85+
)
86+
(local.set $2
87+
(global.get $x_1131)
88+
)
89+
(if
90+
(i32.gt_s
91+
(i32.mul
92+
(i32.load offset=4
93+
(local.get $2)
94+
)
95+
(i32.const -1)
96+
)
97+
(local.get $1)
98+
)
99+
(drop
100+
(block $call_error_handler.5
101+
(drop
102+
(call $printException_0
103+
(global.get $GRAIN$EXPORT$printException_0)
104+
(global.get $GRAIN$EXPORT$IndexOutOfBounds_0)
105+
)
106+
)
107+
(unreachable)
108+
)
109+
)
110+
)
111+
(if
112+
(i32.le_s
113+
(i32.load offset=4
114+
(local.get $2)
115+
)
116+
(local.get $1)
117+
)
118+
(drop
119+
(block $call_error_handler.4
120+
(drop
121+
(call $printException_0
122+
(global.get $GRAIN$EXPORT$printException_0)
123+
(global.get $GRAIN$EXPORT$IndexOutOfBounds_0)
124+
)
125+
)
126+
(unreachable)
127+
)
128+
)
129+
)
130+
(call $incRef_0
131+
(global.get $GRAIN$EXPORT$incRef_0)
132+
(i32.load offset=8
133+
(i32.add
134+
(i32.mul
135+
(if (result i32)
136+
(i32.lt_s
137+
(local.get $1)
138+
(i32.const 0)
139+
)
140+
(i32.add
141+
(local.get $1)
142+
(i32.load offset=4
143+
(local.get $2)
144+
)
145+
)
146+
(local.get $1)
147+
)
148+
(i32.const 4)
149+
)
150+
(local.get $2)
151+
)
152+
)
153+
)
72154
)
73155
)
74156
)
75-
)
76-
(block
77-
(drop
78-
(call $printException_0
79-
(global.get $GRAIN$EXPORT$printException_0)
80-
(global.get $GRAIN$EXPORT$IndexOutOfBounds_0)
81-
)
82-
)
83-
(unreachable)
84-
)
85-
)
86-
(if
87-
(i32.le_s
88-
(i32.load offset=4
89-
(local.get $1)
90-
)
91157
(local.get $0)
92158
)
93-
(block
94-
(drop
95-
(call $printException_0
96-
(global.get $GRAIN$EXPORT$printException_0)
97-
(global.get $GRAIN$EXPORT$IndexOutOfBounds_0)
98-
)
99-
)
100-
(unreachable)
101-
)
102-
)
103-
(call $incRef_0
104-
(global.get $GRAIN$EXPORT$incRef_0)
105-
(i32.load offset=8
106-
(i32.add
107-
(i32.shl
108-
(local.get $0)
109-
(i32.const 2)
110-
)
111-
(local.get $1)
112-
)
113-
)
114159
)
115160
)
116-
(func $_start (; has Stack IR ;)
161+
(func $_start
117162
(drop
118163
(call $_gmain)
119164
)

0 commit comments

Comments
 (0)