Add a mechanism to enable additional (experimental) features and start with sign extension operations; Hashing experimentation

This commit is contained in:
dcodeIO 2018-05-08 00:36:19 +02:00
parent 00fee73022
commit 1bf0ca6525
17 changed files with 2337 additions and 1935 deletions

View File

@ -373,6 +373,18 @@ exports.main = function main(argv, options, callback) {
} }
} }
// Enable additional features if specified
var features = args.feature;
if (features != null) {
if (typeof features === "string") features = features.split(",");
for (let i = 0, k = features.length; i < k; ++i) {
let name = features[i].trim();
let flag = assemblyscript["FEATURE_" + name.toUpperCase()];
if (!flag) return callback(Error("Feature '" + name + "' is invalid."));
assemblyscript.enableFeature(compilerOptions, flag);
}
}
var module; var module;
stats.compileCount++; stats.compileCount++;
(() => { (() => {

View File

@ -149,6 +149,10 @@
], ],
"type": "string" "type": "string"
}, },
"feature": {
"desc": "Enables additional (experimental) WebAssembly features.",
"type": "string"
},
"measure": { "measure": {
"desc": "Prints measuring information on I/O and compile times.", "desc": "Prints measuring information on I/O and compile times.",
"type": "boolean" "type": "boolean"

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

3247
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,7 @@
}, },
"dependencies": { "dependencies": {
"@protobufjs/utf8": "^1.1.0", "@protobufjs/utf8": "^1.1.0",
"binaryen": "47.0.0-nightly.20180503", "binaryen": "47.0.0-nightly.20180507",
"glob": "^7.1.2", "glob": "^7.1.2",
"long": "^4.0.0", "long": "^4.0.0",
"minimist": "^1.2.0", "minimist": "^1.2.0",

View File

@ -173,6 +173,8 @@ export class Options {
sourceMap: bool = false; sourceMap: bool = false;
/** Global aliases. */ /** Global aliases. */
globalAliases: Map<string,string> | null = null; globalAliases: Map<string,string> | null = null;
/** Additional features to activate. */
features: Feature = Feature.NONE;
/** Tests if the target is WASM64 or, otherwise, WASM32. */ /** Tests if the target is WASM64 or, otherwise, WASM32. */
get isWasm64(): bool { get isWasm64(): bool {
@ -193,6 +195,19 @@ export class Options {
get nativeSizeType(): NativeType { get nativeSizeType(): NativeType {
return this.target == Target.WASM64 ? NativeType.I64 : NativeType.I32; return this.target == Target.WASM64 ? NativeType.I64 : NativeType.I32;
} }
/** Tests if a specific feature is activated. */
hasFeature(feature: Feature): bool {
return (this.features & feature) != 0;
}
}
/** Indicates specific features to activate. */
export const enum Feature {
/** No additional features. */
NONE = 0,
/** Sign extension operations. */
SIGNEXT = 1 << 0 // see: https://github.com/WebAssembly/sign-extension-ops
} }
/** Indicates the desired kind of a conversion. */ /** Indicates the desired kind of a conversion. */
@ -237,11 +252,11 @@ export class Compiler extends DiagnosticEmitter {
/** Counting memory offset. */ /** Counting memory offset. */
memoryOffset: I64; memoryOffset: I64;
/** Memory segments being compiled. */ /** Memory segments being compiled. */
memorySegments: MemorySegment[] = new Array(); memorySegments: MemorySegment[] = [];
/** Map of already compiled static string segments. */ /** Map of already compiled static string segments. */
stringSegments: Map<string,MemorySegment> = new Map(); stringSegments: Map<string,MemorySegment> = new Map();
/** Function table being compiled. */ /** Function table being compiled. */
functionTable: Function[] = new Array(); functionTable: Function[] = [];
/** Argument count helper global. */ /** Argument count helper global. */
argcVar: GlobalRef = 0; argcVar: GlobalRef = 0;
/** Argument count helper setter. */ /** Argument count helper setter. */
@ -802,7 +817,7 @@ export class Compiler extends DiagnosticEmitter {
); );
if (!instance) return null; if (!instance) return null;
instance.outerScope = outerScope; instance.outerScope = outerScope;
if (!this.compileFunction(instance)) return null; if (!this.compileFunction(instance)) return null; // reports
return instance; return instance;
} }
@ -868,7 +883,7 @@ export class Compiler extends DiagnosticEmitter {
var module = this.module; var module = this.module;
if (body) { if (body) {
let isConstructor = instance.is(CommonFlags.CONSTRUCTOR); let isConstructor = instance.is(CommonFlags.CONSTRUCTOR);
let returnType: Type = instance.signature.returnType; let returnType = instance.signature.returnType;
// compile body // compile body
let previousFunction = this.currentFunction; let previousFunction = this.currentFunction;
@ -886,6 +901,7 @@ export class Compiler extends DiagnosticEmitter {
); );
flow.set(FlowFlags.RETURNS); flow.set(FlowFlags.RETURNS);
if (!flow.canOverflow(stmt, returnType)) flow.set(FlowFlags.RETURNS_WRAPPED); if (!flow.canOverflow(stmt, returnType)) flow.set(FlowFlags.RETURNS_WRAPPED);
flow.finalize();
} else { } else {
assert(body.kind == NodeKind.BLOCK); assert(body.kind == NodeKind.BLOCK);
stmt = this.compileStatement(body); stmt = this.compileStatement(body);
@ -1179,6 +1195,7 @@ export class Compiler extends DiagnosticEmitter {
compileClass(instance: Class): bool { compileClass(instance: Class): bool {
if (instance.is(CommonFlags.COMPILED)) return true; if (instance.is(CommonFlags.COMPILED)) return true;
instance.set(CommonFlags.COMPILED); instance.set(CommonFlags.COMPILED);
var staticMembers = instance.prototype.members; var staticMembers = instance.prototype.members;
if (staticMembers) { if (staticMembers) {
for (let element of staticMembers.values()) { for (let element of staticMembers.values()) {
@ -6792,9 +6809,11 @@ export class Compiler extends DiagnosticEmitter {
var module = this.module; var module = this.module;
var flow = this.currentFunction.flow; var flow = this.currentFunction.flow;
switch (type.kind) { switch (type.kind) {
case TypeKind.I8: { // TODO: Use 'i32.extend8_s' once sign-extension-ops lands case TypeKind.I8: {
if (flow.canOverflow(expr, type)) { if (flow.canOverflow(expr, type)) {
expr = module.createBinary(BinaryOp.ShrI32, expr = this.options.hasFeature(Feature.SIGNEXT)
? module.createUnary(UnaryOp.ExtendI8ToI32, expr)
: module.createBinary(BinaryOp.ShrI32,
module.createBinary(BinaryOp.ShlI32, module.createBinary(BinaryOp.ShlI32,
expr, expr,
module.createI32(24) module.createI32(24)
@ -6804,9 +6823,11 @@ export class Compiler extends DiagnosticEmitter {
} }
break; break;
} }
case TypeKind.I16: { // TODO: Use 'i32.extend16_s' once sign-extension-ops lands case TypeKind.I16: {
if (flow.canOverflow(expr, type)) { if (flow.canOverflow(expr, type)) {
expr = module.createBinary(BinaryOp.ShrI32, expr = this.options.hasFeature(Feature.SIGNEXT)
? module.createUnary(UnaryOp.ExtendI16ToI32, expr)
: module.createBinary(BinaryOp.ShrI32,
module.createBinary(BinaryOp.ShlI32, module.createBinary(BinaryOp.ShlI32,
expr, expr,
module.createI32(16) module.createI32(16)

View File

@ -115,6 +115,11 @@ declare function _BinaryenPromoteFloat32(): BinaryenOp;
declare function _BinaryenDemoteFloat64(): BinaryenOp; declare function _BinaryenDemoteFloat64(): BinaryenOp;
declare function _BinaryenReinterpretInt32(): BinaryenOp; declare function _BinaryenReinterpretInt32(): BinaryenOp;
declare function _BinaryenReinterpretInt64(): BinaryenOp; declare function _BinaryenReinterpretInt64(): BinaryenOp;
declare function _BinaryenExtendS8Int32(): BinaryenOp;
declare function _BinaryenExtendS16Int32(): BinaryenOp;
declare function _BinaryenExtendS8Int64(): BinaryenOp;
declare function _BinaryenExtendS16Int64(): BinaryenOp;
declare function _BinaryenExtendS32Int64(): BinaryenOp;
declare function _BinaryenAddInt32(): BinaryenOp; declare function _BinaryenAddInt32(): BinaryenOp;
declare function _BinaryenSubInt32(): BinaryenOp; declare function _BinaryenSubInt32(): BinaryenOp;
declare function _BinaryenMulInt32(): BinaryenOp; declare function _BinaryenMulInt32(): BinaryenOp;

View File

@ -6,7 +6,8 @@
import { import {
Compiler, Compiler,
Options, Options,
Target Target,
Feature
} from "./compiler"; } from "./compiler";
import { import {
@ -129,6 +130,14 @@ export function setGlobalAlias(options: Options, name: string, alias: string): v
globalAliases.set(name, alias); globalAliases.set(name, alias);
} }
/** Sign extension operations. */
export const FEATURE_SIGNEXT = Feature.SIGNEXT;
/** Enables a specific feature. */
export function enableFeature(options: Options, feature: Feature): void {
options.features |= feature;
}
/** Finishes parsing. */ /** Finishes parsing. */
export function finishParsing(parser: Parser): Program { export function finishParsing(parser: Parser): Program {
return parser.finish(); return parser.finish();

View File

@ -104,14 +104,14 @@ export enum UnaryOp {
PromoteF32 = _BinaryenPromoteFloat32(), PromoteF32 = _BinaryenPromoteFloat32(),
DemoteF64 = _BinaryenDemoteFloat64(), DemoteF64 = _BinaryenDemoteFloat64(),
ReinterpretI32 = _BinaryenReinterpretInt32(), ReinterpretI32 = _BinaryenReinterpretInt32(),
ReinterpretI64 = _BinaryenReinterpretInt64() ReinterpretI64 = _BinaryenReinterpretInt64(),
// see: https://github.com/WebAssembly/threads/blob/master/proposals/threads/Overview.md#new-sign-extending-operators // see: https://github.com/WebAssembly/sign-extension-ops
// ExtendI8ToI32 =_BinaryenExtendS8Int32() ExtendI8ToI32 = _BinaryenExtendS8Int32(),
// ExtendI16ToI32 = _BinaryenExtendS16Int32() ExtendI16ToI32 = _BinaryenExtendS16Int32(),
// ExtendI8ToI64 = _BinaryenExtendS8Int64() // operand is I64 ExtendI8ToI64 = _BinaryenExtendS8Int64(),
// ExtendI16ToI64 = _BinaryenExtendS16Int64() ExtendI16ToI64 = _BinaryenExtendS16Int64(),
// ExtendI32ToI64 = _BinaryenExtendS32Int64() ExtendI32ToI64 = _BinaryenExtendS32Int64()
// see: https://github.com/WebAssembly/nontrapping-float-to-int-conversions // see: https://github.com/WebAssembly/nontrapping-float-to-int-conversions
// TruncF32ToI32Sat // TruncF32ToI32Sat

View File

@ -505,7 +505,7 @@ export class Signature {
var parameterNames = this.parameterNames; var parameterNames = this.parameterNames;
return parameterNames && parameterNames.length > index return parameterNames && parameterNames.length > index
? parameterNames[index] ? parameterNames[index]
: getGenericParameterName(index); : getDefaultParameterName(index);
} }
/** Tests if a value of this function type is assignable to a target of the specified function type. */ /** Tests if a value of this function type is assignable to a target of the specified function type. */
@ -581,7 +581,7 @@ export class Signature {
if (index) sb.push(", "); if (index) sb.push(", ");
if (i == restIndex) sb.push("..."); if (i == restIndex) sb.push("...");
if (i < numNames) sb.push((<string[]>names)[i]); if (i < numNames) sb.push((<string[]>names)[i]);
else sb.push(getGenericParameterName(i)); else sb.push(getDefaultParameterName(i));
if (i >= optionalStart && i != restIndex) sb.push("?: "); if (i >= optionalStart && i != restIndex) sb.push("?: ");
else sb.push(": "); else sb.push(": ");
sb.push(parameters[i].toString()); sb.push(parameters[i].toString());
@ -595,14 +595,14 @@ export class Signature {
// helpers // helpers
// Cached generic parameter names used where names are unknown. // Cached default parameter names used where names are unknown.
var cachedGenericParameterNames: string[] | null = null; var cachedDefaultParameterNames: string[] | null = null;
/** Gets the cached generic parameter name for the specified index. */ /** Gets the cached default parameter name for the specified index. */
export function getGenericParameterName(index: i32): string { export function getDefaultParameterName(index: i32): string {
if (!cachedGenericParameterNames) cachedGenericParameterNames = []; if (!cachedDefaultParameterNames) cachedDefaultParameterNames = [];
for (let i = cachedGenericParameterNames.length; i <= index; ++i) { for (let i = cachedDefaultParameterNames.length; i <= index; ++i) {
cachedGenericParameterNames.push("arg$" + i.toString(10)); cachedDefaultParameterNames.push("arg$" + i.toString(10));
} }
return cachedGenericParameterNames[index - 1]; return cachedDefaultParameterNames[index - 1];
} }

View File

@ -0,0 +1,61 @@
import {
HEADER_SIZE as HEADER_SIZE_STR
} from "./string";
// FNV-1a 32-bit as a starting point, see: http://isthe.com/chongo/tech/comp/fnv/
const FNV_OFFSET: u32 = 2166136261;
const FNV_PRIME: u32 = 16777619;
export function hash<T>(key: T): u32 {
var hash: u32 = FNV_OFFSET;
if (isString(key)) {
for (let i: usize = 0, k: usize = key.length << 1; i < k; ++i) {
hash = (hash ^ <u32>load<u8>(changetype<usize>(key) + i, HEADER_SIZE_STR)) * FNV_PRIME;
}
} else if (isFloat(key)) {
if (sizeof<T>() == 4) { // f32
let u = reinterpret<u32>(key);
hash = (hash ^ ( u & 0xff)) * FNV_PRIME;
hash = (hash ^ ((u >>> 8) & 0xff)) * FNV_PRIME;
hash = (hash ^ ((u >>> 16) & 0xff)) * FNV_PRIME;
hash = (hash ^ ( u >>> 24 )) * FNV_PRIME;
} else if (sizeof<T>() == 8) { // f64
let u = reinterpret<u64>(key);
let l = <u32> u;
let h = <u32>(u >>> 32);
hash = (hash ^ ( l & 0xff)) * FNV_PRIME;
hash = (hash ^ ((l >>> 8) & 0xff)) * FNV_PRIME;
hash = (hash ^ ((l >>> 16) & 0xff)) * FNV_PRIME;
hash = (hash ^ ( l >>> 24 )) * FNV_PRIME;
hash = (hash ^ ( h & 0xff)) * FNV_PRIME;
hash = (hash ^ ((h >>> 8) & 0xff)) * FNV_PRIME;
hash = (hash ^ ((h >>> 16) & 0xff)) * FNV_PRIME;
hash = (hash ^ ( h >>> 24 )) * FNV_PRIME;
} else unreachable();
} else if (sizeof<T>() == 1) { // bool, i8, u8
hash = (hash ^ (<u32>key & 0xff)) * FNV_PRIME;
} else if (sizeof<T>() == 2) { // i16, u16
let u = <u32>key;
hash = (hash ^ ( u & 0xff)) * FNV_PRIME;
hash = (hash ^ ( u >>> 8 )) * FNV_PRIME;
} else if (sizeof<T>() == 4) { // i32, u32
let u = <u32>key;
hash = (hash ^ ( u & 0xff)) * FNV_PRIME;
hash = (hash ^ ((u >>> 8) & 0xff)) * FNV_PRIME;
hash = (hash ^ ((u >>> 16) & 0xff)) * FNV_PRIME;
hash = (hash ^ ( u >>> 24 )) * FNV_PRIME;
} else if (sizeof<T>() == 8) { // i64, u64
let l = <u32> <u64>key;
let h = <u32>(<u64>key >>> 32);
hash = (hash ^ ( l & 0xff)) * FNV_PRIME;
hash = (hash ^ ((l >>> 8) & 0xff)) * FNV_PRIME;
hash = (hash ^ ((l >>> 16) & 0xff)) * FNV_PRIME;
hash = (hash ^ ( l >>> 24 )) * FNV_PRIME;
hash = (hash ^ ( h & 0xff)) * FNV_PRIME;
hash = (hash ^ ((h >>> 8) & 0xff)) * FNV_PRIME;
hash = (hash ^ ((h >>> 16) & 0xff)) * FNV_PRIME;
hash = (hash ^ ( h >>> 24 )) * FNV_PRIME;
} else unreachable();
return hash;
}

View File

@ -0,0 +1,351 @@
(module
(type $ii (func (param i32) (result i32)))
(type $iv (func (param i32)))
(type $fi (func (param f32) (result i32)))
(type $Fi (func (param f64) (result i32)))
(type $v (func))
(import "env" "logi" (func $std/hash/logi (param i32)))
(memory $0 1)
(data (i32.const 8) "\01\00\00\00a")
(data (i32.const 16) "\02\00\00\00a\00b")
(data (i32.const 24) "\03\00\00\00a\00b\00c")
(export "memory" (memory $0))
(start $start)
(func $~lib/internal/hash/hash<usize> (; 1 ;) (type $ii) (param $0 i32) (result i32)
(local $1 i32)
(i32.mul
(i32.xor
(i32.mul
(i32.xor
(i32.mul
(i32.xor
(i32.mul
(i32.xor
(i32.and
(tee_local $1
(get_local $0)
)
(i32.const 255)
)
(i32.const -2128831035)
)
(i32.const 16777619)
)
(i32.and
(i32.shr_u
(get_local $1)
(i32.const 8)
)
(i32.const 255)
)
)
(i32.const 16777619)
)
(i32.and
(i32.shr_u
(get_local $1)
(i32.const 16)
)
(i32.const 255)
)
)
(i32.const 16777619)
)
(i32.shr_u
(get_local $1)
(i32.const 24)
)
)
(i32.const 16777619)
)
)
(func $~lib/internal/hash/hash<String> (; 2 ;) (type $ii) (param $0 i32) (result i32)
(local $1 i32)
(local $2 i32)
(local $3 i32)
(set_local $2
(i32.const -2128831035)
)
(set_local $3
(i32.shl
(i32.load
(get_local $0)
)
(i32.const 1)
)
)
(loop $continue|0
(if
(i32.lt_u
(get_local $1)
(get_local $3)
)
(block
(set_local $2
(i32.mul
(i32.xor
(get_local $2)
(i32.load8_u offset=4
(i32.add
(get_local $0)
(get_local $1)
)
)
)
(i32.const 16777619)
)
)
(set_local $1
(i32.add
(get_local $1)
(i32.const 1)
)
)
(br $continue|0)
)
)
)
(get_local $2)
)
(func $~lib/internal/hash/hash<f32> (; 3 ;) (type $fi) (param $0 f32) (result i32)
(local $1 i32)
(i32.mul
(i32.xor
(i32.mul
(i32.xor
(i32.mul
(i32.xor
(i32.mul
(i32.xor
(i32.and
(tee_local $1
(i32.reinterpret/f32
(get_local $0)
)
)
(i32.const 255)
)
(i32.const -2128831035)
)
(i32.const 16777619)
)
(i32.and
(i32.shr_u
(get_local $1)
(i32.const 8)
)
(i32.const 255)
)
)
(i32.const 16777619)
)
(i32.and
(i32.shr_u
(get_local $1)
(i32.const 16)
)
(i32.const 255)
)
)
(i32.const 16777619)
)
(i32.shr_u
(get_local $1)
(i32.const 24)
)
)
(i32.const 16777619)
)
)
(func $~lib/internal/hash/hash<f64> (; 4 ;) (type $Fi) (param $0 f64) (result i32)
(local $1 i32)
(local $2 i64)
(i32.mul
(i32.xor
(i32.mul
(i32.xor
(i32.mul
(i32.xor
(i32.mul
(i32.xor
(i32.mul
(i32.xor
(i32.mul
(i32.xor
(i32.mul
(i32.xor
(i32.mul
(i32.xor
(i32.and
(tee_local $1
(i32.wrap/i64
(tee_local $2
(i64.reinterpret/f64
(get_local $0)
)
)
)
)
(i32.const 255)
)
(i32.const -2128831035)
)
(i32.const 16777619)
)
(i32.and
(i32.shr_u
(get_local $1)
(i32.const 8)
)
(i32.const 255)
)
)
(i32.const 16777619)
)
(i32.and
(i32.shr_u
(get_local $1)
(i32.const 16)
)
(i32.const 255)
)
)
(i32.const 16777619)
)
(i32.shr_u
(get_local $1)
(i32.const 24)
)
)
(i32.const 16777619)
)
(i32.and
(tee_local $1
(i32.wrap/i64
(i64.shr_u
(get_local $2)
(i64.const 32)
)
)
)
(i32.const 255)
)
)
(i32.const 16777619)
)
(i32.and
(i32.shr_u
(get_local $1)
(i32.const 8)
)
(i32.const 255)
)
)
(i32.const 16777619)
)
(i32.and
(i32.shr_u
(get_local $1)
(i32.const 16)
)
(i32.const 255)
)
)
(i32.const 16777619)
)
(i32.shr_u
(get_local $1)
(i32.const 24)
)
)
(i32.const 16777619)
)
)
(func $start (; 5 ;) (type $v)
(call $std/hash/logi
(call $~lib/internal/hash/hash<usize>
(i32.const 0)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<String>
(i32.const 4)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<String>
(i32.const 8)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<String>
(i32.const 16)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<String>
(i32.const 24)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<f32>
(f32.const 0)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<f32>
(f32.const 1)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<f32>
(f32.const 1.100000023841858)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<f32>
(f32.const 0)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<f32>
(f32.const inf)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<f32>
(f32.const nan:0x400000)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<f64>
(f64.const 0)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<f64>
(f64.const 1)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<f64>
(f64.const 1.1)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<f64>
(f64.const 0)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<f64>
(f64.const inf)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<f64>
(f64.const nan:0x8000000000000)
)
)
)
)

View File

@ -0,0 +1,23 @@
import { hash } from "internal/hash";
declare function logi(i: i32): void;
logi(hash(null));
logi(hash(""));
logi(hash("a"));
logi(hash("ab"));
logi(hash("abc"));
logi(hash(<f32>0.0));
logi(hash(<f32>1.0));
logi(hash(<f32>1.1));
logi(hash(<f32>-0));
logi(hash(<f32>Infinity));
logi(hash(<f32>NaN));
logi(hash(<f64>0.0));
logi(hash(<f64>1.0));
logi(hash(<f64>1.1));
logi(hash(<f64>-0));
logi(hash(<f64>Infinity));
logi(hash(<f64>NaN));

View File

@ -0,0 +1,453 @@
(module
(type $i (func (result i32)))
(type $ii (func (param i32) (result i32)))
(type $iv (func (param i32)))
(type $fi (func (param f32) (result i32)))
(type $F (func (result f64)))
(type $Fi (func (param f64) (result i32)))
(type $v (func))
(import "env" "logi" (func $std/hash/logi (param i32)))
(global $~lib/internal/allocator/AL_BITS i32 (i32.const 3))
(global $~lib/internal/allocator/AL_SIZE i32 (i32.const 8))
(global $~lib/internal/allocator/AL_MASK i32 (i32.const 7))
(global $~lib/internal/allocator/MAX_SIZE_32 i32 (i32.const 1073741824))
(global $~lib/internal/string/HEADER_SIZE i32 (i32.const 4))
(global $~lib/internal/string/MAX_LENGTH i32 (i32.const 536870910))
(global $~lib/internal/string/EMPTY i32 (i32.const 4))
(global $~lib/internal/hash/FNV_OFFSET i32 (i32.const -2128831035))
(global $~lib/internal/hash/FNV_PRIME i32 (i32.const 16777619))
(global $Infinity f64 (f64.const inf))
(global $NaN f64 (f64.const nan:0x8000000000000))
(global $HEAP_BASE i32 (i32.const 36))
(memory $0 1)
(data (i32.const 4) "\00\00\00\00")
(data (i32.const 8) "\01\00\00\00a\00")
(data (i32.const 16) "\02\00\00\00a\00b\00")
(data (i32.const 24) "\03\00\00\00a\00b\00c\00")
(export "memory" (memory $0))
(start $start)
(func $~lib/internal/hash/hash<usize> (; 1 ;) (type $ii) (param $0 i32) (result i32)
(local $1 i32)
(local $2 i32)
(set_local $1
(i32.const -2128831035)
)
(block
(set_local $2
(get_local $0)
)
(set_local $1
(i32.mul
(i32.xor
(get_local $1)
(i32.and
(get_local $2)
(i32.const 255)
)
)
(i32.const 16777619)
)
)
(set_local $1
(i32.mul
(i32.xor
(get_local $1)
(i32.and
(i32.shr_u
(get_local $2)
(i32.const 8)
)
(i32.const 255)
)
)
(i32.const 16777619)
)
)
(set_local $1
(i32.mul
(i32.xor
(get_local $1)
(i32.and
(i32.shr_u
(get_local $2)
(i32.const 16)
)
(i32.const 255)
)
)
(i32.const 16777619)
)
)
(set_local $1
(i32.mul
(i32.xor
(get_local $1)
(i32.shr_u
(get_local $2)
(i32.const 24)
)
)
(i32.const 16777619)
)
)
)
(return
(get_local $1)
)
)
(func $~lib/internal/hash/hash<String> (; 2 ;) (type $ii) (param $0 i32) (result i32)
(local $1 i32)
(local $2 i32)
(local $3 i32)
(set_local $1
(i32.const -2128831035)
)
(block $break|0
(block
(set_local $2
(i32.const 0)
)
(set_local $3
(i32.shl
(i32.load
(get_local $0)
)
(i32.const 1)
)
)
)
(loop $continue|0
(if
(i32.lt_u
(get_local $2)
(get_local $3)
)
(block
(set_local $1
(i32.mul
(i32.xor
(get_local $1)
(i32.load8_u offset=4
(i32.add
(get_local $0)
(get_local $2)
)
)
)
(i32.const 16777619)
)
)
(set_local $2
(i32.add
(get_local $2)
(i32.const 1)
)
)
(br $continue|0)
)
)
)
)
(return
(get_local $1)
)
)
(func $~lib/internal/hash/hash<f32> (; 3 ;) (type $fi) (param $0 f32) (result i32)
(local $1 i32)
(local $2 i32)
(set_local $1
(i32.const -2128831035)
)
(block
(set_local $2
(i32.reinterpret/f32
(get_local $0)
)
)
(set_local $1
(i32.mul
(i32.xor
(get_local $1)
(i32.and
(get_local $2)
(i32.const 255)
)
)
(i32.const 16777619)
)
)
(set_local $1
(i32.mul
(i32.xor
(get_local $1)
(i32.and
(i32.shr_u
(get_local $2)
(i32.const 8)
)
(i32.const 255)
)
)
(i32.const 16777619)
)
)
(set_local $1
(i32.mul
(i32.xor
(get_local $1)
(i32.and
(i32.shr_u
(get_local $2)
(i32.const 16)
)
(i32.const 255)
)
)
(i32.const 16777619)
)
)
(set_local $1
(i32.mul
(i32.xor
(get_local $1)
(i32.shr_u
(get_local $2)
(i32.const 24)
)
)
(i32.const 16777619)
)
)
)
(return
(get_local $1)
)
)
(func $~lib/internal/hash/hash<f64> (; 4 ;) (type $Fi) (param $0 f64) (result i32)
(local $1 i32)
(local $2 i64)
(local $3 i32)
(local $4 i32)
(set_local $1
(i32.const -2128831035)
)
(block
(set_local $2
(i64.reinterpret/f64
(get_local $0)
)
)
(set_local $3
(i32.wrap/i64
(get_local $2)
)
)
(set_local $4
(i32.wrap/i64
(i64.shr_u
(get_local $2)
(i64.const 32)
)
)
)
(set_local $1
(i32.mul
(i32.xor
(get_local $1)
(i32.and
(get_local $3)
(i32.const 255)
)
)
(i32.const 16777619)
)
)
(set_local $1
(i32.mul
(i32.xor
(get_local $1)
(i32.and
(i32.shr_u
(get_local $3)
(i32.const 8)
)
(i32.const 255)
)
)
(i32.const 16777619)
)
)
(set_local $1
(i32.mul
(i32.xor
(get_local $1)
(i32.and
(i32.shr_u
(get_local $3)
(i32.const 16)
)
(i32.const 255)
)
)
(i32.const 16777619)
)
)
(set_local $1
(i32.mul
(i32.xor
(get_local $1)
(i32.shr_u
(get_local $3)
(i32.const 24)
)
)
(i32.const 16777619)
)
)
(set_local $1
(i32.mul
(i32.xor
(get_local $1)
(i32.and
(get_local $4)
(i32.const 255)
)
)
(i32.const 16777619)
)
)
(set_local $1
(i32.mul
(i32.xor
(get_local $1)
(i32.and
(i32.shr_u
(get_local $4)
(i32.const 8)
)
(i32.const 255)
)
)
(i32.const 16777619)
)
)
(set_local $1
(i32.mul
(i32.xor
(get_local $1)
(i32.and
(i32.shr_u
(get_local $4)
(i32.const 16)
)
(i32.const 255)
)
)
(i32.const 16777619)
)
)
(set_local $1
(i32.mul
(i32.xor
(get_local $1)
(i32.shr_u
(get_local $4)
(i32.const 24)
)
)
(i32.const 16777619)
)
)
)
(return
(get_local $1)
)
)
(func $start (; 5 ;) (type $v)
(call $std/hash/logi
(call $~lib/internal/hash/hash<usize>
(i32.const 0)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<String>
(i32.const 4)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<String>
(i32.const 8)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<String>
(i32.const 16)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<String>
(i32.const 24)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<f32>
(f32.const 0)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<f32>
(f32.const 1)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<f32>
(f32.const 1.100000023841858)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<f32>
(f32.const 0)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<f32>
(f32.const inf)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<f32>
(f32.const nan:0x400000)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<f64>
(f64.const 0)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<f64>
(f64.const 1)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<f64>
(f64.const 1.1)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<f64>
(f64.const 0)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<f64>
(f64.const inf)
)
)
(call $std/hash/logi
(call $~lib/internal/hash/hash<f64>
(f64.const nan:0x8000000000000)
)
)
)
)