Skip to content

Add WASI abort, trace and seed implementations #1159

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Mar 13, 2020
Merged
6 changes: 0 additions & 6 deletions cli/asc.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,12 +248,6 @@ exports.main = function main(argv, options, callback) {
assemblyscript.setNoUnsafe(compilerOptions, args.noUnsafe);
assemblyscript.setPedantic(compilerOptions, args.pedantic);

// Initialize default aliases
assemblyscript.setGlobalAlias(compilerOptions, "Math", "NativeMath");
assemblyscript.setGlobalAlias(compilerOptions, "Mathf", "NativeMathf");
assemblyscript.setGlobalAlias(compilerOptions, "abort", "~lib/builtins/abort");
assemblyscript.setGlobalAlias(compilerOptions, "trace", "~lib/builtins/trace");

// Add or override aliases if specified
if (args.use) {
let aliases = args.use;
Expand Down
9 changes: 6 additions & 3 deletions lib/loader/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,15 @@ function preInstantiate(imports) {
const env = (imports.env = imports.env || {});
env.abort = env.abort || function abort(mesg, file, line, colm) {
const memory = baseModule.memory || env.memory; // prefer exported, otherwise try imported
throw Error("abort: " + getString(memory, mesg) + " at " + getString(memory, file) + ":" + line + ":" + colm);
}
throw Error("abort: " + getString(memory, mesg) + " in " + getString(memory, file) + "(" + line + ":" + colm + ")");
};
env.trace = env.trace || function trace(mesg, n) {
const memory = baseModule.memory || env.memory;
console.log("trace: " + getString(memory, mesg) + (n ? " " : "") + Array.prototype.slice.call(arguments, 2, 2 + n).join(", "));
}
};
env.seed = env.seed || function seed() {
return Date.now();
};
imports.Math = imports.Math || Math;
imports.Date = imports.Date || Date;

Expand Down
9 changes: 9 additions & 0 deletions src/builtins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ export namespace BuiltinNames {
export const setArgumentsLength = "~setArgumentsLength";

// std/builtins.ts
export const abort = "~lib/builtins/abort";
export const trace = "~lib/builtins/trace";
export const seed = "~lib/builtins/seed";

export const isInteger = "~lib/builtins/isInteger";
export const isFloat = "~lib/builtins/isFloat";
export const isBoolean = "~lib/builtins/isBoolean";
Expand Down Expand Up @@ -583,6 +587,11 @@ export namespace BuiltinNames {
export const Uint64Array = "~lib/typedarray/Uint64Array";
export const Float32Array = "~lib/typedarray/Float32Array";
export const Float64Array = "~lib/typedarray/Float64Array";

// std/bindings/wasi.ts
export const wasiAbort = "~lib/wasi/index/abort";
export const wasiTrace = "~lib/wasi/index/trace";
export const wasiSeed = "~lib/wasi/index/seed";
}

/** Builtin compilation context. */
Expand Down
5 changes: 5 additions & 0 deletions src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ export namespace CommonNames {
export const ASC_TABLE_BASE = "ASC_TABLE_BASE";
export const ASC_OPTIMIZE_LEVEL = "ASC_OPTIMIZE_LEVEL";
export const ASC_SHRINK_LEVEL = "ASC_SHRINK_LEVEL";
export const ASC_WASI = "ASC_WASI";
export const ASC_FEATURE_SIGN_EXTENSION = "ASC_FEATURE_SIGN_EXTENSION";
export const ASC_FEATURE_MUTABLE_GLOBALS = "ASC_FEATURE_MUTABLE_GLOBALS";
export const ASC_FEATURE_NONTRAPPING_F2I = "ASC_FEATURE_NONTRAPPING_F2I";
Expand Down Expand Up @@ -189,6 +190,8 @@ export namespace CommonNames {
export const ArrayBuffer = "ArrayBuffer";
export const Math = "Math";
export const Mathf = "Mathf";
export const NativeMath = "NativeMath";
export const NativeMathf = "NativeMathf";
export const Int8Array = "Int8Array";
export const Int16Array = "Int16Array";
export const Int32Array = "Int32Array";
Expand All @@ -203,6 +206,8 @@ export namespace CommonNames {
export const Error = "Error";
// runtime
export const abort = "abort";
export const trace = "trace";
export const seed = "seed";
export const pow = "pow";
export const mod = "mod";
export const alloc = "__alloc";
Expand Down
4 changes: 2 additions & 2 deletions src/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ export class Compiler extends DiagnosticEmitter {

// compile the start function if not empty or if explicitly requested
var startIsEmpty = !startFunctionBody.length;
var explicitStart = options.explicitStart;
var explicitStart = program.isWasi || options.explicitStart;
if (!startIsEmpty || explicitStart) {
let signature = startFunctionInstance.signature;
if (!startIsEmpty && explicitStart) {
Expand Down Expand Up @@ -8832,7 +8832,7 @@ export class Compiler extends DiagnosticEmitter {
reportNode: Node
): ExpressionRef {
var ctor = this.ensureConstructor(classInstance, reportNode);
if (ctor.hasDecorator(DecoratorFlags.UNSAFE)) this.checkUnsafe(reportNode);
if (classInstance.type.isUnmanaged || ctor.hasDecorator(DecoratorFlags.UNSAFE)) this.checkUnsafe(reportNode);
var expr = this.compileCallDirect( // no need for another autoreleased local
ctor,
argumentExpressions,
Expand Down
68 changes: 52 additions & 16 deletions src/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,10 @@ import {
Parser
} from "./parser";

import {
BuiltinNames
} from "./builtins";

/** Represents a yet unresolved `import`. */
class QueuedImport {
constructor(
Expand Down Expand Up @@ -513,6 +517,12 @@ export class Program extends DiagnosticEmitter {
nextSignatureId: i32 = 0;
/** An indicator if the program has been initialized. */
initialized: bool = false;

/** Tests whether this is a WASI program. */
get isWasi(): bool {
return this.elementsByName.has(CommonNames.ASC_WASI);
}

/** Constructs a new program, optionally inheriting parser diagnostics. */
constructor(
/** Compiler options. */
Expand Down Expand Up @@ -1000,23 +1010,49 @@ export class Program extends DiagnosticEmitter {
// set up global aliases
{
let globalAliases = options.globalAliases;
if (globalAliases) {
// TODO: for (let [alias, name] of globalAliases) {
for (let _keys = Map_keys(globalAliases), i = 0, k = _keys.length; i < k; ++i) {
let alias = unchecked(_keys[i]);
let name = assert(globalAliases.get(alias));
if (!name.length) continue; // explicitly disabled
let firstChar = name.charCodeAt(0);
if (firstChar >= CharCode._0 && firstChar <= CharCode._9) {
this.registerConstantInteger(alias, Type.i32, i64_new(<i32>parseInt(name, 10)));
if (!globalAliases) globalAliases = new Map();
let isWasi = this.isWasi;
if (!globalAliases.has(CommonNames.abort)) {
globalAliases.set(CommonNames.abort,
isWasi
? BuiltinNames.wasiAbort
: BuiltinNames.abort
);
}
if (!globalAliases.has(CommonNames.trace)) {
globalAliases.set(CommonNames.trace,
isWasi
? BuiltinNames.wasiTrace
: BuiltinNames.trace
);
}
if (!globalAliases.has(CommonNames.seed)) {
globalAliases.set(CommonNames.seed,
isWasi
? BuiltinNames.wasiSeed
: BuiltinNames.seed
);
}
if (!globalAliases.has(CommonNames.Math)) {
globalAliases.set(CommonNames.Math, CommonNames.NativeMath);
}
if (!globalAliases.has(CommonNames.Mathf)) {
globalAliases.set(CommonNames.Mathf, CommonNames.NativeMathf);
}
// TODO: for (let [alias, name] of globalAliases) {
for (let _keys = Map_keys(globalAliases), i = 0, k = _keys.length; i < k; ++i) {
let alias = unchecked(_keys[i]);
let name = assert(globalAliases.get(alias));
if (!name.length) continue; // explicitly disabled
let firstChar = name.charCodeAt(0);
if (firstChar >= CharCode._0 && firstChar <= CharCode._9) {
this.registerConstantInteger(alias, Type.i32, i64_new(<i32>parseInt(name, 10)));
} else {
let elementsByName = this.elementsByName;
if (elementsByName.has(name)) {
elementsByName.set(alias, assert(elementsByName.get(name)));
} else {
let elementsByName = this.elementsByName;
let element = elementsByName.get(name);
if (element) {
if (elementsByName.has(alias)) throw new Error("duplicate global element: " + name);
elementsByName.set(alias, element);
}
else throw new Error("no such global element: " + name);
throw new Error("no such global element: " + name);
}
}
}
Expand Down
Loading