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
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
const compilerOptions = assemblyscript.createOptions();
assemblyscript.setTarget(compilerOptions, 0);
@ -393,6 +432,7 @@ exports.main = function main(argv, options, callback) {
assemblyscript.setImportTable(compilerOptions, !!args.importTable);
assemblyscript.setMemoryBase(compilerOptions, args.memoryBase >>> 0);
assemblyscript.setSourceMap(compilerOptions, args.sourceMap != null);
assemblyscript.setOptimizeLevelHints(compilerOptions, optimizeLevel, shrinkLevel);
// Initialize default aliases
assemblyscript.setGlobalAlias(compilerOptions, "Math", "NativeMath");
@ -469,51 +509,11 @@ exports.main = function main(argv, options, callback) {
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
// see: https://github.com/WebAssembly/binaryen/pull/1596
if (optimizeLevel >= 3 || shrinkLevel >= 2) optimizeLevel = 4;
module.setOptimizeLevel(optimizeLevel > 0 ? optimizeLevel : 0);
module.setOptimizeLevel(optimizeLevel);
module.setShrinkLevel(shrinkLevel);
module.setDebugInfo(debugInfo);
@ -531,7 +531,7 @@ exports.main = function main(argv, options, callback) {
}
// Optimize the module if requested
if (optimizeLevel >= 0) {
if (optimizeLevel > 0 || shrinkLevel > 0) {
stats.optimizeCount++;
stats.optimizeTime += measure(() => {
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;
/** If true, imports the function table provided by the embedder. */
importTable: bool = false;
/** Static memory start offset. */
memoryBase: u32 = 0;
/** If true, generates information necessary for source maps. */
sourceMap: bool = false;
/** Static memory start offset. */
memoryBase: i32 = 0;
/** Global aliases. */
globalAliases: Map<string,string> | null = null;
/** Additional features to activate. */
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. */
get isWasm64(): bool {
return this.target == Target.WASM64;
@ -251,8 +256,8 @@ export class Compiler extends DiagnosticEmitter {
module: Module;
/** Current function in compilation. */
currentFunction: Function;
/** Outer function in compilation, if compiling a function expression. */
outerFunction: Function | null = null;
/** Current outer function in compilation, if compiling a function expression. */
currentOuterFunction: Function | null = null;
/** Current enum in compilation. */
currentEnum: Enum | null = null;
/** Current type in compilation. */
@ -2045,13 +2050,20 @@ export class Compiler extends DiagnosticEmitter {
let local = new Local(program, name, -1, type);
switch (getExpressionType(initExpr)) {
case NativeType.I32: {
local = local.withConstantIntegerValue(getConstValueI32(initExpr), 0);
local = local.withConstantIntegerValue(
i64_new(
getConstValueI32(initExpr),
0
)
);
break;
}
case NativeType.I64: {
local = local.withConstantIntegerValue(
getConstValueI64Low(initExpr),
getConstValueI64High(initExpr)
i64_new(
getConstValueI64Low(initExpr),
getConstValueI64High(initExpr)
)
);
break;
}

View File

@ -134,6 +134,12 @@ export function enableFeature(options: Options, feature: Feature): void {
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. */
export function finishParsing(parser: Parser): Program {
return parser.finish();

View File

@ -15,7 +15,8 @@ import {
} from "./common";
import {
Options
Options,
Feature
} from "./compiler";
import {
@ -371,6 +372,8 @@ export class Program extends DiagnosticEmitter {
/** Initializes the program and its elements prior to compilation. */
initialize(options: Options): void {
this.options = options;
// add built-in types
this.typesLookup = new Map([
["i8", Type.i8],
["i16", Type.i16],
@ -390,6 +393,25 @@ export class Program extends DiagnosticEmitter {
["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 queuedExports = new Map<string,QueuedExport>();
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. */
private tryResolveImport(
externalName: string,
@ -2670,9 +2710,9 @@ export class VariableLikeElement extends Element {
this.declaration = declaration;
}
withConstantIntegerValue(lo: i32, hi: i32): this {
withConstantIntegerValue(value: I64): this {
this.constantValueKind = ConstantValueKind.INTEGER;
this.constantIntegerValue = i64_new(lo, hi);
this.constantIntegerValue = value;
this.set(CommonFlags.CONST | CommonFlags.INLINED);
return this;
}

17
std/assembly.d.ts vendored
View File

@ -34,6 +34,23 @@ declare type f32 = number;
/** A 64-bit float. */
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. */
declare function i8(value: i8 | i16 | i32 | i64 | isize | u8 | u16 | u32 | u64 | usize | bool | f32 | f64): 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 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. */
declare function i8(value: i8 | i16 | i32 | isize | u8 | u16 | u32 | usize | bool | f32 | f64): i8;
declare namespace i8 {

View File

@ -2,6 +2,8 @@
var globalScope = typeof window !== "undefined" && window || typeof global !== "undefined" && global || self;
globalScope.ASC_TARGET = 0;
Object.defineProperties(
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 path = require("path");
var colors = require("../cli/util/colors");
var glob = require("glob");
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");
var Parser = require("../src/parser").Parser;