Add compiler hints

This commit is contained in:
dcodeIO 2018-06-29 00:14:42 +02:00
parent 3ed4f3331e
commit 82da2d1f6d
15 changed files with 189 additions and 57 deletions

View File

@ -384,6 +384,45 @@ exports.main = function main(argv, options, callback) {
// Finish parsing // Finish parsing
const program = assemblyscript.finishParsing(parser); const program = assemblyscript.finishParsing(parser);
// Set up optimization levels
var optimizeLevel = -1;
var shrinkLevel = 0;
var debugInfo = !args.noDebug;
if (args.optimize !== false) {
if (typeof args.optimize === "number") {
optimizeLevel = args.optimize;
} else if (args["0"]) {
optimizeLevel = 0;
} else if (args["1"]) {
optimizeLevel = 1;
} else if (args["2"]) {
optimizeLevel = 2;
} else if (args["3"]) {
optimizeLevel = 3;
} else if (args.optimize === true) {
optimizeLevel = exports.defaultOptimizeLevel;
shrinkLevel = exports.defaultShrinkLevel;
} else
optimizeLevel = 0;
}
if (args["s"]) {
shrinkLevel = 1;
} else if (args["z"]) {
shrinkLevel = 2;
}
if (typeof args.optimizeLevel === "number") {
optimizeLevel = args.optimizeLevel;
}
if (typeof args.shrinkLevel === "number") {
shrinkLevel = args.shrinkLevel;
} else if (args.shrinkLevel === "s") {
shrinkLevel = 1;
} else if (args.shrinkLevel === "z") {
shrinkLevel = 2;
}
optimizeLevel = Math.max(optimizeLevel, 0);
shrinkLevel = Math.max(shrinkLevel, 0);
// Begin compilation // Begin compilation
const compilerOptions = assemblyscript.createOptions(); const compilerOptions = assemblyscript.createOptions();
assemblyscript.setTarget(compilerOptions, 0); assemblyscript.setTarget(compilerOptions, 0);
@ -393,6 +432,7 @@ exports.main = function main(argv, options, callback) {
assemblyscript.setImportTable(compilerOptions, !!args.importTable); assemblyscript.setImportTable(compilerOptions, !!args.importTable);
assemblyscript.setMemoryBase(compilerOptions, args.memoryBase >>> 0); assemblyscript.setMemoryBase(compilerOptions, args.memoryBase >>> 0);
assemblyscript.setSourceMap(compilerOptions, args.sourceMap != null); assemblyscript.setSourceMap(compilerOptions, args.sourceMap != null);
assemblyscript.setOptimizeLevelHints(compilerOptions, optimizeLevel, shrinkLevel);
// Initialize default aliases // Initialize default aliases
assemblyscript.setGlobalAlias(compilerOptions, "Math", "NativeMath"); assemblyscript.setGlobalAlias(compilerOptions, "Math", "NativeMath");
@ -469,51 +509,11 @@ exports.main = function main(argv, options, callback) {
return callback(Error("Unsupported trap mode")); return callback(Error("Unsupported trap mode"));
} }
var optimizeLevel = -1;
var shrinkLevel = 0;
var debugInfo = !args.noDebug;
if (args.optimize !== false) {
if (typeof args.optimize === "number") {
optimizeLevel = args.optimize;
} else if (args["0"]) {
optimizeLevel = 0;
} else if (args["1"]) {
optimizeLevel = 1;
} else if (args["2"]) {
optimizeLevel = 2;
} else if (args["3"]) {
optimizeLevel = 3;
} else if (args.optimize === true) {
optimizeLevel = exports.defaultOptimizeLevel;
shrinkLevel = exports.defaultShrinkLevel;
} else
optimizeLevel = 0;
}
if (args["s"]) {
shrinkLevel = 1;
} else if (args["z"]) {
shrinkLevel = 2;
}
if (typeof args.optimizeLevel === "number") {
optimizeLevel = args.optimizeLevel;
}
if (typeof args.shrinkLevel === "number") {
shrinkLevel = args.shrinkLevel;
} else if (args.shrinkLevel === "s") {
shrinkLevel = 1;
} else if (args.shrinkLevel === "z") {
shrinkLevel = 2;
}
// Implicitly run costly non-LLVM optimizations on -O3 or -Oz // Implicitly run costly non-LLVM optimizations on -O3 or -Oz
// see: https://github.com/WebAssembly/binaryen/pull/1596 // see: https://github.com/WebAssembly/binaryen/pull/1596
if (optimizeLevel >= 3 || shrinkLevel >= 2) optimizeLevel = 4; if (optimizeLevel >= 3 || shrinkLevel >= 2) optimizeLevel = 4;
module.setOptimizeLevel(optimizeLevel > 0 ? optimizeLevel : 0); module.setOptimizeLevel(optimizeLevel);
module.setShrinkLevel(shrinkLevel); module.setShrinkLevel(shrinkLevel);
module.setDebugInfo(debugInfo); module.setDebugInfo(debugInfo);
@ -531,7 +531,7 @@ exports.main = function main(argv, options, callback) {
} }
// Optimize the module if requested // Optimize the module if requested
if (optimizeLevel >= 0) { if (optimizeLevel > 0 || shrinkLevel > 0) {
stats.optimizeCount++; stats.optimizeCount++;
stats.optimizeTime += measure(() => { stats.optimizeTime += measure(() => {
module.optimize(); module.optimize();

2
dist/asc.js vendored

File diff suppressed because one or more lines are too long

2
dist/asc.js.map vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -177,15 +177,20 @@ export class Options {
importMemory: bool = false; importMemory: bool = false;
/** If true, imports the function table provided by the embedder. */ /** If true, imports the function table provided by the embedder. */
importTable: bool = false; importTable: bool = false;
/** Static memory start offset. */
memoryBase: u32 = 0;
/** If true, generates information necessary for source maps. */ /** If true, generates information necessary for source maps. */
sourceMap: bool = false; sourceMap: bool = false;
/** Static memory start offset. */
memoryBase: i32 = 0;
/** Global aliases. */ /** Global aliases. */
globalAliases: Map<string,string> | null = null; globalAliases: Map<string,string> | null = null;
/** Additional features to activate. */ /** Additional features to activate. */
features: Feature = Feature.NONE; features: Feature = Feature.NONE;
/** Hinted optimize level. Not applied by the compiler itself. */
optimizeLevelHint: i32 = 0;
/** Hinted shrink level. Not applied by the compiler itself. */
shrinkLevelHint: i32 = 0;
/** Tests if the target is WASM64 or, otherwise, WASM32. */ /** Tests if the target is WASM64 or, otherwise, WASM32. */
get isWasm64(): bool { get isWasm64(): bool {
return this.target == Target.WASM64; return this.target == Target.WASM64;
@ -251,8 +256,8 @@ export class Compiler extends DiagnosticEmitter {
module: Module; module: Module;
/** Current function in compilation. */ /** Current function in compilation. */
currentFunction: Function; currentFunction: Function;
/** Outer function in compilation, if compiling a function expression. */ /** Current outer function in compilation, if compiling a function expression. */
outerFunction: Function | null = null; currentOuterFunction: Function | null = null;
/** Current enum in compilation. */ /** Current enum in compilation. */
currentEnum: Enum | null = null; currentEnum: Enum | null = null;
/** Current type in compilation. */ /** Current type in compilation. */
@ -2045,13 +2050,20 @@ export class Compiler extends DiagnosticEmitter {
let local = new Local(program, name, -1, type); let local = new Local(program, name, -1, type);
switch (getExpressionType(initExpr)) { switch (getExpressionType(initExpr)) {
case NativeType.I32: { case NativeType.I32: {
local = local.withConstantIntegerValue(getConstValueI32(initExpr), 0); local = local.withConstantIntegerValue(
i64_new(
getConstValueI32(initExpr),
0
)
);
break; break;
} }
case NativeType.I64: { case NativeType.I64: {
local = local.withConstantIntegerValue( local = local.withConstantIntegerValue(
getConstValueI64Low(initExpr), i64_new(
getConstValueI64High(initExpr) getConstValueI64Low(initExpr),
getConstValueI64High(initExpr)
)
); );
break; break;
} }

View File

@ -134,6 +134,12 @@ export function enableFeature(options: Options, feature: Feature): void {
options.features |= feature; options.features |= feature;
} }
/** Gives the compiler a hint at the optimize levels that will be used later on. */
export function setOptimizeLevelHints(options: Options, optimizeLevel: i32, shrinkLevel: i32): void {
options.optimizeLevelHint = optimizeLevel;
options.shrinkLevelHint = shrinkLevel;
}
/** Finishes parsing. */ /** Finishes parsing. */
export function finishParsing(parser: Parser): Program { export function finishParsing(parser: Parser): Program {
return parser.finish(); return parser.finish();

View File

@ -15,7 +15,8 @@ import {
} from "./common"; } from "./common";
import { import {
Options Options,
Feature
} from "./compiler"; } from "./compiler";
import { import {
@ -371,6 +372,8 @@ export class Program extends DiagnosticEmitter {
/** Initializes the program and its elements prior to compilation. */ /** Initializes the program and its elements prior to compilation. */
initialize(options: Options): void { initialize(options: Options): void {
this.options = options; this.options = options;
// add built-in types
this.typesLookup = new Map([ this.typesLookup = new Map([
["i8", Type.i8], ["i8", Type.i8],
["i16", Type.i16], ["i16", Type.i16],
@ -390,6 +393,25 @@ export class Program extends DiagnosticEmitter {
["boolean", Type.bool] ["boolean", Type.bool]
]); ]);
// add compiler hints
this.setConstantInteger("ASC_TARGET", Type.i32,
i64_new(options.isWasm64 ? 2 : 1));
this.setConstantInteger("ASC_NO_TREESHAKING", Type.bool,
i64_new(options.noTreeShaking ? 1 : 0, 0));
this.setConstantInteger("ASC_NO_ASSERT", Type.bool,
i64_new(options.noAssert ? 1 : 0, 0));
this.setConstantInteger("ASC_MEMORY_BASE", Type.i32,
i64_new(options.memoryBase, 0));
this.setConstantInteger("ASC_OPTIMIZE_LEVEL", Type.i32,
i64_new(options.optimizeLevelHint, 0));
this.setConstantInteger("ASC_SHRINK_LEVEL", Type.i32,
i64_new(options.shrinkLevelHint, 0));
this.setConstantInteger("ASC_FEATURE_MUTABLE_GLOBAL", Type.bool,
i64_new(options.hasFeature(Feature.MUTABLE_GLOBAL) ? 1 : 0, 0));
this.setConstantInteger("ASC_FEATURE_SIGN_EXTENSION", Type.bool,
i64_new(options.hasFeature(Feature.SIGN_EXTENSION) ? 1 : 0, 0));
// remember deferred elements
var queuedImports = new Array<QueuedImport>(); var queuedImports = new Array<QueuedImport>();
var queuedExports = new Map<string,QueuedExport>(); var queuedExports = new Map<string,QueuedExport>();
var queuedExtends = new Array<ClassPrototype>(); var queuedExtends = new Array<ClassPrototype>();
@ -617,6 +639,24 @@ export class Program extends DiagnosticEmitter {
} }
} }
/** Sets a constant integer value. */
setConstantInteger(globalName: string, type: Type, value: I64): void {
assert(type.is(TypeFlags.INTEGER));
this.elementsLookup.set(globalName,
new Global(this, globalName, globalName, type, null, DecoratorFlags.NONE)
.withConstantIntegerValue(value)
);
}
/** Sets a constant float value. */
setConstantFloat(globalName: string, type: Type, value: f64): void {
assert(type.is(TypeFlags.FLOAT));
this.elementsLookup.set(globalName,
new Global(this, globalName, globalName, type, null, DecoratorFlags.NONE)
.withConstantFloatValue(value)
);
}
/** Tries to resolve an import by traversing exports and queued exports. */ /** Tries to resolve an import by traversing exports and queued exports. */
private tryResolveImport( private tryResolveImport(
externalName: string, externalName: string,
@ -2670,9 +2710,9 @@ export class VariableLikeElement extends Element {
this.declaration = declaration; this.declaration = declaration;
} }
withConstantIntegerValue(lo: i32, hi: i32): this { withConstantIntegerValue(value: I64): this {
this.constantValueKind = ConstantValueKind.INTEGER; this.constantValueKind = ConstantValueKind.INTEGER;
this.constantIntegerValue = i64_new(lo, hi); this.constantIntegerValue = value;
this.set(CommonFlags.CONST | CommonFlags.INLINED); this.set(CommonFlags.CONST | CommonFlags.INLINED);
return this; return this;
} }

17
std/assembly.d.ts vendored
View File

@ -34,6 +34,23 @@ declare type f32 = number;
/** A 64-bit float. */ /** A 64-bit float. */
declare type f64 = number; declare type f64 = number;
/** Compiler target. 0 = JS, 1 = WASM32, 2 = WASM64. */
declare const ASC_TARGET: i32;
/** Provided noTreeshaking option. */
declare const ASC_NO_TREESHAKING: bool;
/** Provided noAssert option. */
declare const ASC_NO_ASSERT: bool;
/** Provided memoryBase option. */
declare const ASC_MEMORY_BASE: i32;
/** Provided optimizeLevel option. */
declare const ASC_OPTIMIZE_LEVEL: i32;
/** Provided shrinkLevel option. */
declare const ASC_SHRINK_LEVEL: i32;
/** Whether the mutable global feature is enabled. */
declare const ASC_FEATURE_MUTABLE_GLOBAL: bool;
/** Whether the sign extension feature is enabled. */
declare const ASC_FEATURE_SIGN_EXTENSION: bool;
/** Converts any other numeric value to an 8-bit signed integer. */ /** Converts any other numeric value to an 8-bit signed integer. */
declare function i8(value: i8 | i16 | i32 | i64 | isize | u8 | u16 | u32 | u64 | usize | bool | f32 | f64): i8; declare function i8(value: i8 | i16 | i32 | i64 | isize | u8 | u16 | u32 | u64 | usize | bool | f32 | f64): i8;
declare namespace i8 { declare namespace i8 {

3
std/portable.d.ts vendored
View File

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

View File

@ -2,6 +2,8 @@
var globalScope = typeof window !== "undefined" && window || typeof global !== "undefined" && global || self; var globalScope = typeof window !== "undefined" && window || typeof global !== "undefined" && global || self;
globalScope.ASC_TARGET = 0;
Object.defineProperties( Object.defineProperties(
globalScope["i8"] = function i8(value) { return value << 24 >> 24; } globalScope["i8"] = function i8(value) { return value << 24 >> 24; }
, { , {

View File

@ -0,0 +1,4 @@
(module
(memory $0 0)
(export "memory" (memory $0))
)

View File

@ -0,0 +1,8 @@
ASC_TARGET;
ASC_NO_TREESHAKING;
ASC_NO_ASSERT;
ASC_MEMORY_BASE;
ASC_OPTIMIZE_LEVEL;
ASC_SHRINK_LEVEL;
ASC_FEATURE_MUTABLE_GLOBAL;
ASC_FEATURE_SIGN_EXTENSION;

View File

@ -0,0 +1,33 @@
(module
(type $v (func))
(global $HEAP_BASE i32 (i32.const 8))
(memory $0 0)
(export "memory" (memory $0))
(start $start)
(func $start (; 0 ;) (type $v)
(drop
(i32.const 1)
)
(drop
(i32.const 0)
)
(drop
(i32.const 0)
)
(drop
(i32.const 0)
)
(drop
(i32.const 0)
)
(drop
(i32.const 0)
)
(drop
(i32.const 0)
)
(drop
(i32.const 0)
)
)
)

View File

@ -1,9 +1,16 @@
var fs = require("fs"); var fs = require("fs");
var path = require("path");
var colors = require("../cli/util/colors"); var colors = require("../cli/util/colors");
var glob = require("glob"); var glob = require("glob");
var diff = require("./util/diff"); var diff = require("./util/diff");
require("ts-node").register({ project: require("path").join(__dirname, "..", "src", "tsconfig.json") }); require("ts-node").register({
project: require("path").join(__dirname, "..", "src", "tsconfig.json"),
files: [ // see: https://github.com/TypeStrong/ts-node/issues/620
path.join(__dirname, "..", "std", "portable.d.ts"),
path.join(__dirname, "..", "src", "glue", "binaryen.d.ts")
]
});
require("../src/glue/js"); require("../src/glue/js");
var Parser = require("../src/parser").Parser; var Parser = require("../src/parser").Parser;