Skip to content

Commit 82da2d1

Browse files
committed
Add compiler hints
1 parent 3ed4f33 commit 82da2d1

15 files changed

+189
-57
lines changed

cli/asc.js

+42-42
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,45 @@ exports.main = function main(argv, options, callback) {
384384
// Finish parsing
385385
const program = assemblyscript.finishParsing(parser);
386386

387+
// Set up optimization levels
388+
var optimizeLevel = -1;
389+
var shrinkLevel = 0;
390+
var debugInfo = !args.noDebug;
391+
if (args.optimize !== false) {
392+
if (typeof args.optimize === "number") {
393+
optimizeLevel = args.optimize;
394+
} else if (args["0"]) {
395+
optimizeLevel = 0;
396+
} else if (args["1"]) {
397+
optimizeLevel = 1;
398+
} else if (args["2"]) {
399+
optimizeLevel = 2;
400+
} else if (args["3"]) {
401+
optimizeLevel = 3;
402+
} else if (args.optimize === true) {
403+
optimizeLevel = exports.defaultOptimizeLevel;
404+
shrinkLevel = exports.defaultShrinkLevel;
405+
} else
406+
optimizeLevel = 0;
407+
}
408+
if (args["s"]) {
409+
shrinkLevel = 1;
410+
} else if (args["z"]) {
411+
shrinkLevel = 2;
412+
}
413+
if (typeof args.optimizeLevel === "number") {
414+
optimizeLevel = args.optimizeLevel;
415+
}
416+
if (typeof args.shrinkLevel === "number") {
417+
shrinkLevel = args.shrinkLevel;
418+
} else if (args.shrinkLevel === "s") {
419+
shrinkLevel = 1;
420+
} else if (args.shrinkLevel === "z") {
421+
shrinkLevel = 2;
422+
}
423+
optimizeLevel = Math.max(optimizeLevel, 0);
424+
shrinkLevel = Math.max(shrinkLevel, 0);
425+
387426
// Begin compilation
388427
const compilerOptions = assemblyscript.createOptions();
389428
assemblyscript.setTarget(compilerOptions, 0);
@@ -393,6 +432,7 @@ exports.main = function main(argv, options, callback) {
393432
assemblyscript.setImportTable(compilerOptions, !!args.importTable);
394433
assemblyscript.setMemoryBase(compilerOptions, args.memoryBase >>> 0);
395434
assemblyscript.setSourceMap(compilerOptions, args.sourceMap != null);
435+
assemblyscript.setOptimizeLevelHints(compilerOptions, optimizeLevel, shrinkLevel);
396436

397437
// Initialize default aliases
398438
assemblyscript.setGlobalAlias(compilerOptions, "Math", "NativeMath");
@@ -469,51 +509,11 @@ exports.main = function main(argv, options, callback) {
469509
return callback(Error("Unsupported trap mode"));
470510
}
471511

472-
var optimizeLevel = -1;
473-
var shrinkLevel = 0;
474-
var debugInfo = !args.noDebug;
475-
476-
if (args.optimize !== false) {
477-
if (typeof args.optimize === "number") {
478-
optimizeLevel = args.optimize;
479-
} else if (args["0"]) {
480-
optimizeLevel = 0;
481-
} else if (args["1"]) {
482-
optimizeLevel = 1;
483-
} else if (args["2"]) {
484-
optimizeLevel = 2;
485-
} else if (args["3"]) {
486-
optimizeLevel = 3;
487-
} else if (args.optimize === true) {
488-
optimizeLevel = exports.defaultOptimizeLevel;
489-
shrinkLevel = exports.defaultShrinkLevel;
490-
} else
491-
optimizeLevel = 0;
492-
}
493-
494-
if (args["s"]) {
495-
shrinkLevel = 1;
496-
} else if (args["z"]) {
497-
shrinkLevel = 2;
498-
}
499-
500-
if (typeof args.optimizeLevel === "number") {
501-
optimizeLevel = args.optimizeLevel;
502-
}
503-
504-
if (typeof args.shrinkLevel === "number") {
505-
shrinkLevel = args.shrinkLevel;
506-
} else if (args.shrinkLevel === "s") {
507-
shrinkLevel = 1;
508-
} else if (args.shrinkLevel === "z") {
509-
shrinkLevel = 2;
510-
}
511-
512512
// Implicitly run costly non-LLVM optimizations on -O3 or -Oz
513513
// see: https://github.com/WebAssembly/binaryen/pull/1596
514514
if (optimizeLevel >= 3 || shrinkLevel >= 2) optimizeLevel = 4;
515515

516-
module.setOptimizeLevel(optimizeLevel > 0 ? optimizeLevel : 0);
516+
module.setOptimizeLevel(optimizeLevel);
517517
module.setShrinkLevel(shrinkLevel);
518518
module.setDebugInfo(debugInfo);
519519

@@ -531,7 +531,7 @@ exports.main = function main(argv, options, callback) {
531531
}
532532

533533
// Optimize the module if requested
534-
if (optimizeLevel >= 0) {
534+
if (optimizeLevel > 0 || shrinkLevel > 0) {
535535
stats.optimizeCount++;
536536
stats.optimizeTime += measure(() => {
537537
module.optimize();

dist/asc.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/asc.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/assemblyscript.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/assemblyscript.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/compiler.ts

+19-7
Original file line numberDiff line numberDiff line change
@@ -177,15 +177,20 @@ export class Options {
177177
importMemory: bool = false;
178178
/** If true, imports the function table provided by the embedder. */
179179
importTable: bool = false;
180-
/** Static memory start offset. */
181-
memoryBase: u32 = 0;
182180
/** If true, generates information necessary for source maps. */
183181
sourceMap: bool = false;
182+
/** Static memory start offset. */
183+
memoryBase: i32 = 0;
184184
/** Global aliases. */
185185
globalAliases: Map<string,string> | null = null;
186186
/** Additional features to activate. */
187187
features: Feature = Feature.NONE;
188188

189+
/** Hinted optimize level. Not applied by the compiler itself. */
190+
optimizeLevelHint: i32 = 0;
191+
/** Hinted shrink level. Not applied by the compiler itself. */
192+
shrinkLevelHint: i32 = 0;
193+
189194
/** Tests if the target is WASM64 or, otherwise, WASM32. */
190195
get isWasm64(): bool {
191196
return this.target == Target.WASM64;
@@ -251,8 +256,8 @@ export class Compiler extends DiagnosticEmitter {
251256
module: Module;
252257
/** Current function in compilation. */
253258
currentFunction: Function;
254-
/** Outer function in compilation, if compiling a function expression. */
255-
outerFunction: Function | null = null;
259+
/** Current outer function in compilation, if compiling a function expression. */
260+
currentOuterFunction: Function | null = null;
256261
/** Current enum in compilation. */
257262
currentEnum: Enum | null = null;
258263
/** Current type in compilation. */
@@ -2045,13 +2050,20 @@ export class Compiler extends DiagnosticEmitter {
20452050
let local = new Local(program, name, -1, type);
20462051
switch (getExpressionType(initExpr)) {
20472052
case NativeType.I32: {
2048-
local = local.withConstantIntegerValue(getConstValueI32(initExpr), 0);
2053+
local = local.withConstantIntegerValue(
2054+
i64_new(
2055+
getConstValueI32(initExpr),
2056+
0
2057+
)
2058+
);
20492059
break;
20502060
}
20512061
case NativeType.I64: {
20522062
local = local.withConstantIntegerValue(
2053-
getConstValueI64Low(initExpr),
2054-
getConstValueI64High(initExpr)
2063+
i64_new(
2064+
getConstValueI64Low(initExpr),
2065+
getConstValueI64High(initExpr)
2066+
)
20552067
);
20562068
break;
20572069
}

src/index.ts

+6
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,12 @@ export function enableFeature(options: Options, feature: Feature): void {
134134
options.features |= feature;
135135
}
136136

137+
/** Gives the compiler a hint at the optimize levels that will be used later on. */
138+
export function setOptimizeLevelHints(options: Options, optimizeLevel: i32, shrinkLevel: i32): void {
139+
options.optimizeLevelHint = optimizeLevel;
140+
options.shrinkLevelHint = shrinkLevel;
141+
}
142+
137143
/** Finishes parsing. */
138144
export function finishParsing(parser: Parser): Program {
139145
return parser.finish();

src/program.ts

+43-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ import {
1515
} from "./common";
1616

1717
import {
18-
Options
18+
Options,
19+
Feature
1920
} from "./compiler";
2021

2122
import {
@@ -371,6 +372,8 @@ export class Program extends DiagnosticEmitter {
371372
/** Initializes the program and its elements prior to compilation. */
372373
initialize(options: Options): void {
373374
this.options = options;
375+
376+
// add built-in types
374377
this.typesLookup = new Map([
375378
["i8", Type.i8],
376379
["i16", Type.i16],
@@ -390,6 +393,25 @@ export class Program extends DiagnosticEmitter {
390393
["boolean", Type.bool]
391394
]);
392395

396+
// add compiler hints
397+
this.setConstantInteger("ASC_TARGET", Type.i32,
398+
i64_new(options.isWasm64 ? 2 : 1));
399+
this.setConstantInteger("ASC_NO_TREESHAKING", Type.bool,
400+
i64_new(options.noTreeShaking ? 1 : 0, 0));
401+
this.setConstantInteger("ASC_NO_ASSERT", Type.bool,
402+
i64_new(options.noAssert ? 1 : 0, 0));
403+
this.setConstantInteger("ASC_MEMORY_BASE", Type.i32,
404+
i64_new(options.memoryBase, 0));
405+
this.setConstantInteger("ASC_OPTIMIZE_LEVEL", Type.i32,
406+
i64_new(options.optimizeLevelHint, 0));
407+
this.setConstantInteger("ASC_SHRINK_LEVEL", Type.i32,
408+
i64_new(options.shrinkLevelHint, 0));
409+
this.setConstantInteger("ASC_FEATURE_MUTABLE_GLOBAL", Type.bool,
410+
i64_new(options.hasFeature(Feature.MUTABLE_GLOBAL) ? 1 : 0, 0));
411+
this.setConstantInteger("ASC_FEATURE_SIGN_EXTENSION", Type.bool,
412+
i64_new(options.hasFeature(Feature.SIGN_EXTENSION) ? 1 : 0, 0));
413+
414+
// remember deferred elements
393415
var queuedImports = new Array<QueuedImport>();
394416
var queuedExports = new Map<string,QueuedExport>();
395417
var queuedExtends = new Array<ClassPrototype>();
@@ -617,6 +639,24 @@ export class Program extends DiagnosticEmitter {
617639
}
618640
}
619641

642+
/** Sets a constant integer value. */
643+
setConstantInteger(globalName: string, type: Type, value: I64): void {
644+
assert(type.is(TypeFlags.INTEGER));
645+
this.elementsLookup.set(globalName,
646+
new Global(this, globalName, globalName, type, null, DecoratorFlags.NONE)
647+
.withConstantIntegerValue(value)
648+
);
649+
}
650+
651+
/** Sets a constant float value. */
652+
setConstantFloat(globalName: string, type: Type, value: f64): void {
653+
assert(type.is(TypeFlags.FLOAT));
654+
this.elementsLookup.set(globalName,
655+
new Global(this, globalName, globalName, type, null, DecoratorFlags.NONE)
656+
.withConstantFloatValue(value)
657+
);
658+
}
659+
620660
/** Tries to resolve an import by traversing exports and queued exports. */
621661
private tryResolveImport(
622662
externalName: string,
@@ -2670,9 +2710,9 @@ export class VariableLikeElement extends Element {
26702710
this.declaration = declaration;
26712711
}
26722712

2673-
withConstantIntegerValue(lo: i32, hi: i32): this {
2713+
withConstantIntegerValue(value: I64): this {
26742714
this.constantValueKind = ConstantValueKind.INTEGER;
2675-
this.constantIntegerValue = i64_new(lo, hi);
2715+
this.constantIntegerValue = value;
26762716
this.set(CommonFlags.CONST | CommonFlags.INLINED);
26772717
return this;
26782718
}

std/assembly.d.ts

+17
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,23 @@ declare type f32 = number;
3434
/** A 64-bit float. */
3535
declare type f64 = number;
3636

37+
/** Compiler target. 0 = JS, 1 = WASM32, 2 = WASM64. */
38+
declare const ASC_TARGET: i32;
39+
/** Provided noTreeshaking option. */
40+
declare const ASC_NO_TREESHAKING: bool;
41+
/** Provided noAssert option. */
42+
declare const ASC_NO_ASSERT: bool;
43+
/** Provided memoryBase option. */
44+
declare const ASC_MEMORY_BASE: i32;
45+
/** Provided optimizeLevel option. */
46+
declare const ASC_OPTIMIZE_LEVEL: i32;
47+
/** Provided shrinkLevel option. */
48+
declare const ASC_SHRINK_LEVEL: i32;
49+
/** Whether the mutable global feature is enabled. */
50+
declare const ASC_FEATURE_MUTABLE_GLOBAL: bool;
51+
/** Whether the sign extension feature is enabled. */
52+
declare const ASC_FEATURE_SIGN_EXTENSION: bool;
53+
3754
/** Converts any other numeric value to an 8-bit signed integer. */
3855
declare function i8(value: i8 | i16 | i32 | i64 | isize | u8 | u16 | u32 | u64 | usize | bool | f32 | f64): i8;
3956
declare namespace i8 {

std/portable.d.ts

+3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ declare type usize = number;
2828
declare type f32 = number;
2929
declare type f64 = number;
3030

31+
/** Compiler target. 0 = JS, 1 = WASM32, 2 = WASM64. */
32+
declare const ASC_TARGET: i32;
33+
3134
/** Converts any other numeric value to an 8-bit signed integer. */
3235
declare function i8(value: i8 | i16 | i32 | isize | u8 | u16 | u32 | usize | bool | f32 | f64): i8;
3336
declare namespace i8 {

std/portable.js

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
var globalScope = typeof window !== "undefined" && window || typeof global !== "undefined" && global || self;
44

5+
globalScope.ASC_TARGET = 0;
6+
57
Object.defineProperties(
68
globalScope["i8"] = function i8(value) { return value << 24 >> 24; }
79
, {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
(module
2+
(memory $0 0)
3+
(export "memory" (memory $0))
4+
)

tests/compiler/asc-constants.ts

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
ASC_TARGET;
2+
ASC_NO_TREESHAKING;
3+
ASC_NO_ASSERT;
4+
ASC_MEMORY_BASE;
5+
ASC_OPTIMIZE_LEVEL;
6+
ASC_SHRINK_LEVEL;
7+
ASC_FEATURE_MUTABLE_GLOBAL;
8+
ASC_FEATURE_SIGN_EXTENSION;
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
(module
2+
(type $v (func))
3+
(global $HEAP_BASE i32 (i32.const 8))
4+
(memory $0 0)
5+
(export "memory" (memory $0))
6+
(start $start)
7+
(func $start (; 0 ;) (type $v)
8+
(drop
9+
(i32.const 1)
10+
)
11+
(drop
12+
(i32.const 0)
13+
)
14+
(drop
15+
(i32.const 0)
16+
)
17+
(drop
18+
(i32.const 0)
19+
)
20+
(drop
21+
(i32.const 0)
22+
)
23+
(drop
24+
(i32.const 0)
25+
)
26+
(drop
27+
(i32.const 0)
28+
)
29+
(drop
30+
(i32.const 0)
31+
)
32+
)
33+
)

tests/parser.js

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
var fs = require("fs");
2+
var path = require("path");
23
var colors = require("../cli/util/colors");
34
var glob = require("glob");
45
var diff = require("./util/diff");
56

6-
require("ts-node").register({ project: require("path").join(__dirname, "..", "src", "tsconfig.json") });
7+
require("ts-node").register({
8+
project: require("path").join(__dirname, "..", "src", "tsconfig.json"),
9+
files: [ // see: https://github.com/TypeStrong/ts-node/issues/620
10+
path.join(__dirname, "..", "std", "portable.d.ts"),
11+
path.join(__dirname, "..", "src", "glue", "binaryen.d.ts")
12+
]
13+
});
714
require("../src/glue/js");
815

916
var Parser = require("../src/parser").Parser;

0 commit comments

Comments
 (0)