Revised implicit type conversions; Initial function expression compilation

This commit is contained in:
dcodeIO 2018-02-28 01:48:01 +01:00
parent bda6cb9792
commit d4c00eaba3
36 changed files with 940 additions and 1754 deletions

2
dist/asc.js 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

@ -721,7 +721,7 @@ export abstract class Node {
static createFunctionDeclaration(
name: IdentifierExpression,
typeParameters: TypeParameter[],
typeParameters: TypeParameter[] | null,
parameters: Parameter[],
returnType: TypeNode | null,
body: Statement | null,
@ -732,7 +732,7 @@ export abstract class Node {
var stmt = new FunctionDeclaration();
stmt.range = range;
stmt.name = name; name.parent = stmt;
stmt.typeParameters = typeParameters; setParent(typeParameters, stmt);
stmt.typeParameters = typeParameters; if (typeParameters) setParent(typeParameters, stmt);
stmt.parameters = parameters; setParent(parameters, stmt);
stmt.returnType = returnType; if (returnType) returnType.parent = stmt;
stmt.body = body; if (body) body.parent = stmt;
@ -743,7 +743,7 @@ export abstract class Node {
static createMethodDeclaration(
name: IdentifierExpression,
typeParameters: TypeParameter[],
typeParameters: TypeParameter[] | null,
parameters: Parameter[],
returnType: TypeNode | null,
body: Statement | null,
@ -754,7 +754,7 @@ export abstract class Node {
var stmt = new MethodDeclaration();
stmt.range = range;
stmt.name = name; name.parent = stmt;
stmt.typeParameters = typeParameters; setParent(typeParameters, stmt);
stmt.typeParameters = typeParameters; if (typeParameters) setParent(typeParameters, stmt);
stmt.parameters = parameters; setParent(parameters, stmt);
stmt.returnType = returnType; if (returnType) returnType.parent = stmt;
stmt.body = body; if (body) body.parent = stmt;
@ -1490,13 +1490,17 @@ export class FunctionDeclaration extends DeclarationStatement {
kind = NodeKind.FUNCTIONDECLARATION;
/** Accepted type parameters. */
typeParameters: TypeParameter[];
typeParameters: TypeParameter[] | null;
/** Accepted parameters. */
parameters: Parameter[];
/** Return type. */
returnType: TypeNode | null;
/** Body statement. Usually a block. */
body: Statement | null;
get isGeneric(): bool {
return this.typeParameters != null && this.typeParameters.length > 0;
}
}
/** Represents an `if` statement. */

View File

@ -2303,7 +2303,7 @@ function evaluateConstantOffset(compiler: Compiler, expression: Expression): i32
var expr: ExpressionRef;
var value: i32;
if (compiler.options.isWasm64) {
expr = compiler.precomputeExpression(expression, Type.i64);
expr = compiler.precomputeExpression(expression, Type.usize64);
if (
_BinaryenExpressionGetId(expr) != ExpressionId.Const ||
_BinaryenExpressionGetType(expr) != NativeType.I64 ||
@ -2317,7 +2317,7 @@ function evaluateConstantOffset(compiler: Compiler, expression: Expression): i32
value = -1;
}
} else {
expr = compiler.precomputeExpression(expression, Type.i32);
expr = compiler.precomputeExpression(expression, Type.usize32);
if (
_BinaryenExpressionGetId(expr) != ExpressionId.Const ||
_BinaryenExpressionGetType(expr) != NativeType.I32 ||

View File

@ -88,6 +88,7 @@ import {
CommaExpression,
ElementAccessExpression,
FloatLiteralExpression,
FunctionExpression,
IdentifierExpression,
IntegerLiteralExpression,
LiteralExpression,
@ -200,6 +201,9 @@ export class Compiler extends DiagnosticEmitter {
/** Map of already compiled static string segments. */
stringSegments: Map<string,MemorySegment> = new Map();
/** Function table being compiled. */
functionTable: Function[] = new Array();
/** Already processed file names. */
files: Set<string> = new Set();
@ -294,6 +298,16 @@ export class Compiler extends DiagnosticEmitter {
"memory"
);
}
// set up function table
if (k = this.functionTable.length) {
var entries = new Array<FunctionRef>(k);
for (i = 0; i < k; ++i) {
entries[i] = this.functionTable[i].ref;
}
this.module.setFunctionTable(entries);
}
return this.module;
}
@ -376,7 +390,7 @@ export class Compiler extends DiagnosticEmitter {
noTreeShaking ||
(isEntry && hasModifier(ModifierKind.EXPORT, (<FunctionDeclaration>statement).modifiers))
) &&
!(<FunctionDeclaration>statement).typeParameters.length
!(<FunctionDeclaration>statement).isGeneric
) {
this.compileFunctionDeclaration(<FunctionDeclaration>statement, []);
}
@ -868,7 +882,8 @@ export class Compiler extends DiagnosticEmitter {
(
noTreeShaking ||
hasModifier(ModifierKind.EXPORT, (<FunctionDeclaration>member).modifiers)
) && !(<FunctionDeclaration>member).typeParameters.length
) &&
!(<FunctionDeclaration>member).isGeneric
) {
this.compileFunctionDeclaration(<FunctionDeclaration>member, []);
}
@ -1068,7 +1083,7 @@ export class Compiler extends DiagnosticEmitter {
// memory
/** Adds a static memory segment with the specified data. */
/** Adds a static memory segment with the specified data. */
addMemorySegment(buffer: Uint8Array, alignment: i32 = 8): MemorySegment {
var memoryOffset = i64_align(this.memoryOffset, alignment);
var segment = MemorySegment.create(buffer, memoryOffset);
@ -1077,6 +1092,20 @@ export class Compiler extends DiagnosticEmitter {
return segment;
}
// function table
/** Adds a function table entry and returns the assigned index. */
addFunctionTableEntry(func: Function): i32 {
assert(func.is(ElementFlags.COMPILED));
if (func.functionTableIndex >= 0) {
return func.functionTableIndex;
}
var index = this.functionTable.length;
this.functionTable.push(func);
func.functionTableIndex = index;
return index;
}
// statements
compileStatement(statement: Statement): ExpressionRef {
@ -1241,7 +1270,11 @@ export class Compiler extends DiagnosticEmitter {
this.currentFunction.flow.breakLabel = previousBreakLabel;
this.currentFunction.flow.continueLabel = previousContinueLabel;
var condition = this.compileExpression(statement.condition, Type.i32);
var condition = makeIsTrueish(
this.compileExpression(statement.condition, Type.i32, ConversionKind.NONE),
this.currentType,
this.module
);
this.currentFunction.leaveBreakContext();
@ -1319,7 +1352,11 @@ export class Compiler extends DiagnosticEmitter {
compileIfStatement(statement: IfStatement): ExpressionRef {
// The condition doesn't initiate a branch yet
var condition = this.compileExpression(statement.condition, Type.i32);
var condition = makeIsTrueish(
this.compileExpression(statement.condition, Type.i32, ConversionKind.NONE),
this.currentType,
this.module
);
// Each arm initiates a branch
this.currentFunction.flow = this.currentFunction.flow.enterBranchOrScope();
@ -1359,14 +1396,14 @@ export class Compiler extends DiagnosticEmitter {
var context = this.currentFunction.enterBreakContext();
// introduce a local for evaluating the condition (exactly once)
var tempLocal = this.currentFunction.getTempLocal(Type.i32);
var tempLocal = this.currentFunction.getTempLocal(Type.u32);
var k = statement.cases.length;
// Prepend initializer to inner block. Does not initiate a new branch, yet.
var breaks = new Array<ExpressionRef>(1 + k);
breaks[0] = this.module.createSetLocal( // initializer
tempLocal.index,
this.compileExpression(statement.condition, Type.i32)
this.compileExpression(statement.condition, Type.u32)
);
// make one br_if per (possibly dynamic) labeled case (binaryen optimizes to br_table where possible)
@ -1577,7 +1614,11 @@ export class Compiler extends DiagnosticEmitter {
compileWhileStatement(statement: WhileStatement): ExpressionRef {
// The condition does not yet initialize a branch
var condition = this.compileExpression(statement.condition, Type.i32);
var condition = makeIsTrueish(
this.compileExpression(statement.condition, Type.i32, ConversionKind.NONE),
this.currentType,
this.module
);
// Statements initiate a new branch with its own break context
var label = this.currentFunction.enterBreakContext();
@ -1715,6 +1756,11 @@ export class Compiler extends DiagnosticEmitter {
expr = this.compileElementAccessExpression(<ElementAccessExpression>expression, contextualType);
break;
case NodeKind.FUNCTION:
case NodeKind.FUNCTIONARROW:
expr = this.compileFunctionExpression(<FunctionExpression>expression, contextualType);
break;
case NodeKind.IDENTIFIER:
case NodeKind.FALSE:
case NodeKind.NULL:
@ -1817,6 +1863,13 @@ export class Compiler extends DiagnosticEmitter {
return this.module.createDrop(expr);
}
if (conversionKind == ConversionKind.IMPLICIT && !fromType.isAssignableTo(toType)) {
this.error(
DiagnosticCode.Conversion_from_type_0_to_1_requires_an_explicit_cast,
reportNode.range, fromType.toString(), toType.toString()
);
}
var mod = this.module;
var losesInformation = false;
@ -1974,13 +2027,6 @@ export class Compiler extends DiagnosticEmitter {
// otherwise (smaller) i32/u32 to (same size) i32/u32
}
if (losesInformation && conversionKind == ConversionKind.IMPLICIT) {
this.error(
DiagnosticCode.Conversion_from_type_0_to_1_possibly_loses_information_and_thus_requires_an_explicit_cast,
reportNode.range, fromType.toString(), toType.toString()
);
}
return expr;
}
@ -3768,6 +3814,25 @@ export class Compiler extends DiagnosticEmitter {
], expression);
}
compileFunctionExpression(expression: FunctionExpression, contextualType: Type): ExpressionRef {
var declaration = expression.declaration;
var simpleName = (declaration.name.text.length
? declaration.name.text
: "anonymous") + "|" + this.functionTable.length.toString(10);
var prototype = new FunctionPrototype(
this.program,
simpleName,
this.currentFunction.internalName + "~" + simpleName,
declaration
);
var instance = this.compileFunctionUsingTypeArguments(prototype, [], null, declaration);
if (!instance) return this.module.createUnreachable();
this.currentType = Type.u32.asFunction(instance);
var index = this.addFunctionTableEntry(instance);
if (index < 0) return this.module.createUnreachable();
return this.module.createI32(index);
}
compileIdentifierExpression(expression: IdentifierExpression, contextualType: Type): ExpressionRef {
// check special keywords first
switch (expression.kind) {
@ -4045,7 +4110,8 @@ export class Compiler extends DiagnosticEmitter {
this.stringSegments.set(stringValue, stringSegment);
}
var stringOffset = stringSegment.offset;
this.currentType = this.options.usizeType;
var stringType = this.program.types.get("string");
this.currentType = stringType ? stringType : this.options.usizeType;
if (this.options.isWasm64) {
return this.module.createI64(i64_low(stringOffset), i64_high(stringOffset));
}
@ -4244,7 +4310,8 @@ export class Compiler extends DiagnosticEmitter {
assert((<Field>element).memoryOffset >= 0);
targetExpr = this.compileExpression(
<Expression>resolved.targetExpression,
this.options.usizeType
this.options.usizeType,
ConversionKind.NONE
);
this.currentType = (<Field>element).type;
return this.module.createLoad(
@ -4265,9 +4332,8 @@ export class Compiler extends DiagnosticEmitter {
if (getterInstance.is(ElementFlags.INSTANCE)) {
targetExpr = this.compileExpression(
<Expression>resolved.targetExpression,
this.options.isWasm64
? Type.usize64
: Type.usize32
this.options.usizeType,
ConversionKind.NONE
);
this.currentType = getterInstance.returnType;
return this.makeCall(getterInstance, [ targetExpr ]);
@ -4283,7 +4349,11 @@ export class Compiler extends DiagnosticEmitter {
}
compileTernaryExpression(expression: TernaryExpression, contextualType: Type): ExpressionRef {
var condition = this.compileExpression(expression.condition, Type.i32);
var condition = makeIsTrueish(
this.compileExpression(expression.condition, Type.u32, ConversionKind.NONE),
this.currentType,
this.module
);
var ifThen = this.compileExpression(expression.ifThen, contextualType);
var ifElse = this.compileExpression(expression.ifElse, contextualType);
return this.module.createIf(condition, ifThen, ifElse);
@ -4308,6 +4378,13 @@ export class Compiler extends DiagnosticEmitter {
switch (expression.operator) {
case Token.PLUS_PLUS:
if (this.currentType.isReference) {
this.error(
DiagnosticCode.Operation_not_supported,
expression.range
);
return this.module.createUnreachable();
}
switch (this.currentType.kind) {
case TypeKind.I8:
@ -4363,6 +4440,13 @@ export class Compiler extends DiagnosticEmitter {
break;
case Token.MINUS_MINUS:
if (this.currentType.isReference) {
this.error(
DiagnosticCode.Operation_not_supported,
expression.range
);
return this.module.createUnreachable();
}
switch (this.currentType.kind) {
case TypeKind.I8:
@ -4496,6 +4580,13 @@ export class Compiler extends DiagnosticEmitter {
break;
case Token.MINUS:
if (this.currentType.isReference) {
this.error(
DiagnosticCode.Operation_not_supported,
expression.range
);
return this.module.createUnreachable();
}
if (expression.operand.kind == NodeKind.LITERAL && (
(<LiteralExpression>expression.operand).literalKind == LiteralKind.INTEGER ||
(<LiteralExpression>expression.operand).literalKind == LiteralKind.FLOAT
@ -4559,6 +4650,13 @@ export class Compiler extends DiagnosticEmitter {
break;
case Token.PLUS_PLUS:
if (this.currentType.isReference) {
this.error(
DiagnosticCode.Operation_not_supported,
expression.range
);
return this.module.createUnreachable();
}
compound = true;
expr = this.compileExpression(
expression.operand,
@ -4616,6 +4714,13 @@ export class Compiler extends DiagnosticEmitter {
break;
case Token.MINUS_MINUS:
if (this.currentType.isReference) {
this.error(
DiagnosticCode.Operation_not_supported,
expression.range
);
return this.module.createUnreachable();
}
compound = true;
expr = this.compileExpression(
expression.operand,
@ -4687,6 +4792,13 @@ export class Compiler extends DiagnosticEmitter {
break;
case Token.TILDE:
if (this.currentType.isReference) {
this.error(
DiagnosticCode.Operation_not_supported,
expression.range
);
return this.module.createUnreachable();
}
expr = this.compileExpression(
expression.operand,
contextualType == Type.void
@ -4866,13 +4978,13 @@ export function makeIsFalseish(expr: ExpressionRef, type: Type, module: Module):
}
/** Creates a comparison whether an expression is 'true' in a broader sense. */
export function makeIsTrueish(expr: ExpressionRef, type: Type, module: Module): ExpressionRef {
export function makeIsTrueish(
expr: ExpressionRef,
type: Type,
module: Module
): ExpressionRef {
switch (type.kind) {
default: // any integer up to 32 bits
expr = module.createBinary(BinaryOp.NeI32, expr, module.createI32(0));
break;
case TypeKind.I64:
case TypeKind.U64:
expr = module.createBinary(BinaryOp.NeI64, expr, module.createI64(0));
@ -4881,9 +4993,9 @@ export function makeIsTrueish(expr: ExpressionRef, type: Type, module: Module):
case TypeKind.USIZE:
// TODO: strings
case TypeKind.ISIZE:
expr = type.size == 64
? module.createBinary(BinaryOp.NeI64, expr, module.createI64(0))
: module.createBinary(BinaryOp.NeI32, expr, module.createI32(0));
if (type.size == 64) {
expr = module.createBinary(BinaryOp.NeI64, expr, module.createI64(0));
}
break;
case TypeKind.F32:

View File

@ -4,7 +4,7 @@
export enum DiagnosticCode {
Operation_not_supported = 100,
Operation_is_unsafe = 101,
Conversion_from_type_0_to_1_possibly_loses_information_and_thus_requires_an_explicit_cast = 200,
Conversion_from_type_0_to_1_requires_an_explicit_cast = 200,
Conversion_from_type_0_to_1_will_require_an_explicit_cast_when_switching_between_32_64_bit = 201,
Type_0_cannot_be_changed_to_type_1 = 202,
Type_0_cannot_be_reinterpreted_as_type_1 = 203,
@ -101,7 +101,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
switch (code) {
case 100: return "Operation not supported.";
case 101: return "Operation is unsafe.";
case 200: return "Conversion from type '{0}' to '{1}' possibly loses information and thus requires an explicit cast.";
case 200: return "Conversion from type '{0}' to '{1}' requires an explicit cast.";
case 201: return "Conversion from type '{0}' to '{1}' will require an explicit cast when switching between 32/64-bit.";
case 202: return "Type '{0}' cannot be changed to type '{1}'.";
case 203: return "Type '{0}' cannot be reinterpreted as type '{1}'.";

View File

@ -1,7 +1,7 @@
{
"Operation not supported.": 100,
"Operation is unsafe.": 101,
"Conversion from type '{0}' to '{1}' possibly loses information and thus requires an explicit cast.": 200,
"Conversion from type '{0}' to '{1}' requires an explicit cast.": 200,
"Conversion from type '{0}' to '{1}' will require an explicit cast when switching between 32/64-bit.": 201,
"Type '{0}' cannot be changed to type '{1}'.": 202,
"Type '{0}' cannot be reinterpreted as type '{1}'.": 203,

View File

@ -876,14 +876,16 @@ export function serializeFunctionDeclaration(node: FunctionDeclaration, sb: stri
function serializeFunctionCommon(node: FunctionDeclaration, sb: string[], isArrow: bool = false): void {
var i: i32, k: i32;
serializeIdentifierExpression(node.name, sb);
if (k = node.typeParameters.length) {
sb.push("<");
serializeTypeParameter(node.typeParameters[0], sb);
for (i = 1; i < k; ++i) {
sb.push(", ");
serializeTypeParameter(node.typeParameters[i], sb);
if (node.typeParameters) {
if (k = node.typeParameters.length) {
sb.push("<");
serializeTypeParameter(node.typeParameters[0], sb);
for (i = 1; i < k; ++i) {
sb.push(", ");
serializeTypeParameter(node.typeParameters[i], sb);
}
sb.push(">");
}
sb.push(">");
}
sb.push("(");
if (k = node.parameters.length) {

View File

@ -56,6 +56,7 @@ import {
ExportStatement,
ExpressionStatement,
ForStatement,
FunctionExpression,
FunctionDeclaration,
IfStatement,
ImportDeclaration,
@ -79,8 +80,7 @@ import {
addModifier,
getModifier,
hasModifier,
setReusableModifiers,
FunctionExpression
setReusableModifiers
} from "./ast";
@ -874,8 +874,6 @@ export class Parser extends DiagnosticEmitter {
if (tn.skip(Token.LESSTHAN)) {
typeParameters = this.parseTypeParameters(tn);
if (!typeParameters) return null;
} else {
typeParameters = [];
}
if (!tn.skip(Token.OPENPAREN)) {
@ -1046,7 +1044,7 @@ export class Parser extends DiagnosticEmitter {
var declaration = Node.createFunctionDeclaration(
identifier,
[],
null,
parameters,
returnType,
body,
@ -1213,7 +1211,7 @@ export class Parser extends DiagnosticEmitter {
? Node.createConstructorExpression(tn.range())
: Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
var typeParameters: TypeParameter[] | null;
var typeParameters: TypeParameter[] | null = null;
if (tn.skip(Token.LESSTHAN)) {
if (isConstructor) {
this.error(
@ -1223,8 +1221,6 @@ export class Parser extends DiagnosticEmitter {
}
typeParameters = this.parseTypeParameters(tn);
if (!typeParameters) return null;
} else {
typeParameters = [];
}
// method: '(' Parameters (':' Type)? '{' Statement* '}' ';'?

View File

@ -474,12 +474,18 @@ export class Program extends DiagnosticEmitter {
// check and possibly register string type
if (
prototype.is(ElementFlags.GLOBAL) &&
declaration.name.text === "String" &&
!this.types.has("string")
declaration.name.text == "String"
) {
var instance = prototype.resolve(null);
if (instance) {
this.types.set("string", instance.type);
if (!this.types.has("string")) {
var instance = prototype.resolve(null);
if (instance) {
this.types.set("string", instance.type);
}
} else {
this.error(
DiagnosticCode.Duplicate_identifier_0,
declaration.name.range, declaration.programLevelInternalName
);
}
}
}
@ -2116,7 +2122,7 @@ export class FunctionPrototype extends Element {
}
}
}
if (this.declaration.typeParameters.length) {
if (this.declaration.isGeneric) {
this.set(ElementFlags.GENERIC);
}
if (this.classPrototype = classPrototype) {
@ -2163,7 +2169,7 @@ export class FunctionPrototype extends Element {
// override call specific contextual type arguments
var functionTypeParameters = declaration.typeParameters;
if (functionTypeArguments && (k = functionTypeArguments.length)) {
if (k != functionTypeParameters.length) {
if (!functionTypeParameters || k != functionTypeParameters.length) {
throw new Error("type argument count mismatch");
}
for (i = 0; i < k; ++i) {
@ -2229,7 +2235,7 @@ export class FunctionPrototype extends Element {
if (this.is(ElementFlags.GENERIC)) {
assert(typeArgumentNodes != null && typeArgumentNodes.length != 0);
resolvedTypeArguments = this.program.resolveTypeArguments(
this.declaration.typeParameters,
assert(this.declaration.typeParameters),
typeArgumentNodes,
contextualTypeArguments,
reportNode
@ -2288,6 +2294,10 @@ export class Function extends Element {
flow: Flow;
/** Remembered debug locations. */
debugLocations: Range[] | null = null;
/** Function reference, if compiled. */
ref: FunctionRef = 0;
/** Function table index, if any. */
functionTableIndex: i32 = -1;
private nextBreakId: i32 = 0;
private breakStack: i32[] | null = null;
@ -2444,6 +2454,7 @@ export class Function extends Element {
/** Finalizes the function once compiled, releasing no longer needed resources. */
finalize(module: Module, ref: FunctionRef): void {
this.ref = ref;
assert(!this.breakStack || !this.breakStack.length); // internal error
this.breakStack = null;
this.breakContext = null;
@ -2466,6 +2477,11 @@ export class Function extends Element {
this.debugLocations = null;
}
/** Tests if a value of this function type is assignable to a target of the specified function type. */
isAssignableTo(target: Function): bool {
return this == target; // TODO
}
/** Returns the TypeScript representation of this function. */
toString(): string { return this.prototype.simpleName; }
@ -2865,6 +2881,17 @@ export class Class extends Element {
}
}
/** Tests if a value of this class type is assignable to a target of the specified class type. */
isAssignableTo(target: Class): bool {
var current: Class | null = this;
do {
if (current == target) {
return true;
}
} while (current = current.base);
return false;
}
toString(): string {
return this.prototype.simpleName;
}

View File

@ -122,7 +122,7 @@ export class Type {
/** Composes a function type from this type and a function. */
asFunction(functionType: Function): Type {
assert(this.kind == TypeKind.USIZE && !this.isReference);
assert(this.kind == TypeKind.U32 && !this.isReference);
var ret = new Type(this.kind, this.flags & ~TypeFlags.VALUE | TypeFlags.REFERENCE, this.size);
ret.functionType = functionType;
return ret;
@ -140,6 +140,196 @@ export class Type {
return this.nullableType;
}
/** Tests if a value of this type is assignable to a target of the specified type. */
isAssignableTo(target: Type): bool {
var currentClass: Class | null;
var targetClass: Class | null;
var currentFunction: Function | null;
var targetFunction: Function | null;
if (this.isReference) {
if (target.isReference) {
if (currentClass = this.classType) {
if (targetClass = target.classType) {
return currentClass.isAssignableTo(targetClass);
}
} else if (currentFunction = this.functionType) {
if (targetFunction = target.functionType) {
return currentFunction.isAssignableTo(targetFunction);
}
}
}
} else if (!target.isReference) {
switch (this.kind) {
case TypeKind.I8:
switch (target.kind) {
case TypeKind.I8: // same
case TypeKind.I16: // larger
case TypeKind.I32: // larger
case TypeKind.I64: // larger
case TypeKind.ISIZE: // larger
case TypeKind.U8: // signed to unsigned
case TypeKind.U16: // larger
case TypeKind.U32: // larger
case TypeKind.U64: // larger
case TypeKind.USIZE: // larger
case TypeKind.F32: // safe
case TypeKind.F64: // safe
return true;
}
break;
case TypeKind.I16:
switch (target.kind) {
case TypeKind.I16: // same
case TypeKind.I32: // larger
case TypeKind.I64: // larger
case TypeKind.ISIZE: // larger
case TypeKind.U16: // signed to unsigned
case TypeKind.U32: // larger
case TypeKind.U64: // larger
case TypeKind.USIZE: // larger
case TypeKind.F32: // safe
case TypeKind.F64: // safe
return true;
}
break;
case TypeKind.I32:
switch (target.kind) {
case TypeKind.I32: // same
case TypeKind.I64: // larger
case TypeKind.ISIZE: // same or larger
case TypeKind.U32: // signed to unsigned
case TypeKind.U64: // larger
case TypeKind.USIZE: // signed to unsigned or larger
case TypeKind.F64: // safe
return true;
}
break;
case TypeKind.I64:
switch (target.kind) {
case TypeKind.I64: // same
case TypeKind.U64: // signed to unsigned
return true;
case TypeKind.ISIZE: // possibly same
case TypeKind.USIZE: // possibly signed to unsigned
return target.size == 64;
}
break;
case TypeKind.ISIZE:
switch (target.kind) {
case TypeKind.I32: // possibly same
case TypeKind.U32: // possibly signed to unsigned
return this.size == 32;
case TypeKind.I64: // same or larger
case TypeKind.ISIZE: // same
case TypeKind.U64: // signed to unsigned or larger
case TypeKind.USIZE: // signed to unsigned
return true;
case TypeKind.F64: // possibly safe
return target.size == 32;
}
break;
case TypeKind.U8:
switch (target.kind) {
case TypeKind.I16: // larger
case TypeKind.I32: // larger
case TypeKind.I64: // larger
case TypeKind.ISIZE: // larger
case TypeKind.U8: // same
case TypeKind.U16: // larger
case TypeKind.U32: // larger
case TypeKind.U64: // larger
case TypeKind.USIZE: // larger
case TypeKind.F32: // safe
case TypeKind.F64: // safe
return true;
}
break;
case TypeKind.U16:
switch (target.kind) {
case TypeKind.I32: // larger
case TypeKind.I64: // larger
case TypeKind.ISIZE: // larger
case TypeKind.U16: // same
case TypeKind.U32: // larger
case TypeKind.U64: // larger
case TypeKind.USIZE: // larger
case TypeKind.F32: // safe
case TypeKind.F64: // safe
return true;
}
break;
case TypeKind.U32:
switch (target.kind) {
case TypeKind.I64: // larger
case TypeKind.U32: // same
case TypeKind.U64: // larger
case TypeKind.USIZE: // same or larger
case TypeKind.F64: // safe
return true;
}
break;
case TypeKind.U64:
switch (target.kind) {
case TypeKind.U64: // same
return true;
case TypeKind.USIZE: // possibly same
return target.size == 64;
}
break;
case TypeKind.USIZE:
switch (target.kind) {
case TypeKind.U32: // possibly same
return this.size == 32;
case TypeKind.U64: // same or larger
case TypeKind.USIZE: // same
return true;
case TypeKind.F64: // possibly safe
return target.size == 32;
}
break;
case TypeKind.BOOL:
switch (target.kind) {
case TypeKind.I8: // larger
case TypeKind.I16: // larger
case TypeKind.I32: // larger
case TypeKind.I64: // larger
case TypeKind.ISIZE: // larger
case TypeKind.U8: // larger
case TypeKind.U16: // larger
case TypeKind.U32: // larger
case TypeKind.U64: // larger
case TypeKind.USIZE: // larger
case TypeKind.BOOL: // same
return true;
}
break;
case TypeKind.F32:
switch (target.kind) {
case TypeKind.F32: // same
case TypeKind.F64: // larger
return true;
}
break;
case TypeKind.F64:
return target.kind == TypeKind.F64;
}
}
return false;
}
/** Converts this type to its TypeScript representation. */
toString(kindOnly: bool = false): string {
switch (this.kind) {

View File

@ -17,7 +17,7 @@ export function allocate_memory(size: usize): usize {
var off = (ptr + size + ALIGN_MASK) & ~ALIGN_MASK;
var avail = <usize>current_memory() << 16;
if (off > avail && grow_memory(
max(
<i32>max(
(((off + 0xffff) & ~0xffff) - avail) >> 16, // minimum required pages
avail >> 16 // at least double memory
)

View File

@ -8,7 +8,7 @@ export class Array<T> {
assert(newCapacity > this.__capacity);
var newMemory = allocate_memory(<usize>newCapacity * sizeof<T>());
if (this.__memory) {
move_memory(newMemory, this.__memory, this.__capacity * sizeof<T>());
move_memory(newMemory, this.__memory, <usize>this.__capacity * sizeof<T>());
free_memory(this.__memory);
}
this.__memory = newMemory;
@ -63,7 +63,7 @@ export class Array<T> {
fromIndex = this.__length + fromIndex;
}
while (<u32>fromIndex < this.__length) {
if (load<T>(this.__memory + fromIndex * sizeof<T>()) == searchElement) {
if (load<T>(this.__memory + <usize>fromIndex * sizeof<T>()) == searchElement) {
return fromIndex;
}
++fromIndex;
@ -78,7 +78,7 @@ export class Array<T> {
fromIndex = this.__length - 1;
}
while (fromIndex >= 0) {
if (load<T>(this.__memory + fromIndex * sizeof<T>()) == searchElement) {
if (load<T>(this.__memory + <usize>fromIndex * sizeof<T>()) == searchElement) {
return fromIndex;
}
--fromIndex;
@ -90,7 +90,7 @@ export class Array<T> {
if (this.__length == this.__capacity) {
this.__grow(this.__capacity ? this.__capacity << 1 : 1);
}
store<T>(this.__memory + this.__length * sizeof<T>(), element);
store<T>(this.__memory + <usize>this.__length * sizeof<T>(), element);
return ++this.__length;
}
@ -98,7 +98,7 @@ export class Array<T> {
if (this.__length < 1) {
throw new RangeError("Array is empty"); // return changetype<T>(0) ?
}
return load<T>(this.__memory + --this.__length * sizeof<T>());
return load<T>(this.__memory + <usize>--this.__length * sizeof<T>());
}
shift(): T {
@ -109,10 +109,10 @@ export class Array<T> {
move_memory(
this.__memory,
this.__memory + sizeof<T>(),
(this.__capacity - 1) * sizeof<T>()
<usize>(this.__capacity - 1) * sizeof<T>()
);
set_memory(
this.__memory + (this.__capacity - 1) * sizeof<T>(),
this.__memory + <usize>(this.__capacity - 1) * sizeof<T>(),
0,
sizeof<T>()
);
@ -131,7 +131,7 @@ export class Array<T> {
move_memory(
newMemory + sizeof<T>(),
this.__memory,
oldCapacity * sizeof<T>()
<usize>oldCapacity * sizeof<T>()
);
free_memory(this.__memory);
}
@ -141,7 +141,7 @@ export class Array<T> {
move_memory(
this.__memory + sizeof<T>(),
this.__memory,
oldCapacity * sizeof<T>()
<usize>oldCapacity * sizeof<T>()
);
}
store<T>(this.__memory, element);
@ -196,7 +196,7 @@ export class Array<T> {
move_memory(
this.__memory + <usize>start * sizeof<T>(),
this.__memory + <usize>(start + deleteCount) * sizeof<T>(),
deleteCount * sizeof<T>()
<usize>deleteCount * sizeof<T>()
);
this.__length -= deleteCount;
}

View File

@ -133,10 +133,10 @@ declare function isize(value: void): isize;
namespace isize {
export const MIN_VALUE: isize = sizeof<i32>() == sizeof<isize>()
? -2147483648
: <usize>-9223372036854775808;
: <isize>-9223372036854775808;
export const MAX_VALUE: isize = sizeof<i32>() == sizeof<isize>()
? 2147483647
: <usize>9223372036854775807;
: <isize>9223372036854775807;
}
export { isize };

View File

@ -13,7 +13,7 @@ export class Set<T> {
}
get size(): i32 {
return this.__size;
return <i32>this.__size;
}
// FIXME: not a proper set implementation, just a filler
@ -52,11 +52,11 @@ export class Set<T> {
for (var index: usize = 0, limit: usize = this.__size; index < limit; ++index) {
if (load<T>(this.__memory + index * sizeof<T>()) == value) {
if (index + 1 < this.__size) {
if (index + 1 < limit) {
move_memory(
this.__memory + index * sizeof<T>(),
this.__memory + (index + 1) * sizeof<T>(),
this.__size - index - 1
limit - index - 1
);
}
--this.__size;

View File

@ -63,34 +63,28 @@
(if
(i32.and
(if (result i32)
(i32.ne
(tee_local $8
(i32.and
(if (result i32)
(i32.ne
(tee_local $8
(i64.eq
(i64.shl
(get_local $3)
(i64.const 1)
)
(i64.const 0)
)
(tee_local $8
(i32.and
(if (result i32)
(tee_local $8
(i64.eq
(i64.shl
(get_local $3)
(i64.const 1)
)
(i32.const 0)
)
(get_local $8)
(f64.ne
(tee_local $7
(get_local $1)
)
(get_local $7)
(i64.const 0)
)
)
(i32.const 1)
(get_local $8)
(f64.ne
(tee_local $7
(get_local $1)
)
(get_local $7)
)
)
(i32.const 1)
)
(i32.const 0)
)
(get_local $8)
(i32.eq
@ -517,34 +511,28 @@
(if
(i32.and
(if (result i32)
(i32.ne
(tee_local $8
(i32.and
(if (result i32)
(i32.ne
(tee_local $8
(i32.eq
(i32.shl
(get_local $3)
(i32.const 1)
)
(i32.const 0)
)
(tee_local $8
(i32.and
(if (result i32)
(tee_local $8
(i32.eq
(i32.shl
(get_local $3)
(i32.const 1)
)
(i32.const 0)
)
(get_local $8)
(f32.ne
(tee_local $7
(get_local $1)
)
(get_local $7)
)
)
(i32.const 1)
(get_local $8)
(f32.ne
(tee_local $7
(get_local $1)
)
(get_local $7)
)
)
(i32.const 1)
)
(i32.const 0)
)
(get_local $8)
(i32.eq

View File

@ -0,0 +1,15 @@
(module
(type $ii (func (param i32) (result i32)))
(type $v (func))
(table 3 3 anyfunc)
(elem (i32.const 0) $start~anonymous|0 $start~anonymous|0 $start~someName|2)
(memory $0 1)
(export "memory" (memory $0))
(start $start~someName|2)
(func $start~anonymous|0 (; 0 ;) (type $ii) (param $0 i32) (result i32)
(get_local $0)
)
(func $start~someName|2 (; 1 ;) (type $v)
(nop)
)
)

View File

@ -0,0 +1,11 @@
var f1 = function(a: i32): i32 {
return a;
};
f1;
var f2 = (a: i32): i32 => {
return a;
};
f2;
var f3 = function someName(): void {
};
f3;

View File

@ -0,0 +1,36 @@
(module
(type $ii (func (param i32) (result i32)))
(type $v (func))
(global $function-expression/f1 (mut i32) (i32.const 0))
(global $function-expression/f2 (mut i32) (i32.const 1))
(global $function-expression/f3 (mut i32) (i32.const 2))
(global $HEAP_BASE i32 (i32.const 4))
(table 3 3 anyfunc)
(elem (i32.const 0) $start~anonymous|0 $start~anonymous|1 $start~someName|2)
(memory $0 1)
(export "memory" (memory $0))
(start $start)
(func $start~anonymous|0 (; 0 ;) (type $ii) (param $0 i32) (result i32)
(return
(get_local $0)
)
)
(func $start~anonymous|1 (; 1 ;) (type $ii) (param $0 i32) (result i32)
(return
(get_local $0)
)
)
(func $start~someName|2 (; 2 ;) (type $v)
)
(func $start (; 3 ;) (type $v)
(drop
(get_global $function-expression/f1)
)
(drop
(get_global $function-expression/f2)
)
(drop
(get_global $function-expression/f3)
)
)
)

View File

@ -229,14 +229,11 @@
(if
(i32.and
(if (result i32)
(i32.ne
(tee_local $9
(i32.lt_s
(get_local $8)
(i32.const 2)
)
(tee_local $9
(i32.lt_s
(get_local $8)
(i32.const 2)
)
(i32.const 0)
)
(get_local $9)
(i32.gt_s

View File

@ -16,10 +16,7 @@
(local $1 f64)
(drop
(if (result i32)
(i32.ne
(i32.const 0)
(i32.const 0)
)
(i32.const 0)
(unreachable)
(i32.const 0)
)
@ -36,10 +33,7 @@
)
(drop
(if (result i32)
(i32.ne
(i32.const 1)
(i32.const 0)
)
(i32.const 1)
(i32.const 1)
(unreachable)
)
@ -56,18 +50,12 @@
)
(drop
(if (result i32)
(i32.ne
(tee_local $0
(if (result i32)
(i32.ne
(i32.const 1)
(i32.const 0)
)
(i32.const 2)
(i32.const 1)
)
(tee_local $0
(if (result i32)
(i32.const 1)
(i32.const 2)
(i32.const 1)
)
(i32.const 0)
)
(get_local $0)
(unreachable)
@ -94,10 +82,7 @@
)
(set_global $logical/i
(if (result i32)
(i32.ne
(i32.const 1)
(i32.const 0)
)
(i32.const 1)
(i32.const 2)
(i32.const 1)
)
@ -121,10 +106,7 @@
)
(set_global $logical/i
(if (result i32)
(i32.ne
(i32.const 0)
(i32.const 0)
)
(i32.const 0)
(i32.const 0)
(i32.const 1)
)

View File

@ -24,10 +24,7 @@
(loop $continue|0
(if
(if (result i32)
(i32.ne
(get_local $2)
(i32.const 0)
)
(get_local $2)
(i32.rem_u
(get_local $1)
(i32.const 4)

View File

@ -1,4 +1,4 @@
function test(a: i32, b: i32): void {
function test(a: u32, b: u32): void {
// signed
assert(<i8>(a + b) == <i8>(<i8>a + <i8>b));

View File

@ -111,10 +111,7 @@
(loop $continue|0
(if
(if (result i32)
(i32.ne
(get_local $2)
(i32.const 0)
)
(get_local $2)
(i32.rem_u
(get_local $1)
(i32.const 4)
@ -1959,34 +1956,28 @@
(if
(i32.and
(if (result i32)
(i32.ne
(tee_local $8
(i32.and
(if (result i32)
(i32.ne
(tee_local $8
(i64.eq
(i64.shl
(get_local $3)
(i64.const 1)
)
(i64.const 0)
)
(tee_local $8
(i32.and
(if (result i32)
(tee_local $8
(i64.eq
(i64.shl
(get_local $3)
(i64.const 1)
)
(i32.const 0)
)
(get_local $8)
(f64.ne
(tee_local $7
(get_local $1)
)
(get_local $7)
(i64.const 0)
)
)
(i32.const 1)
(get_local $8)
(f64.ne
(tee_local $7
(get_local $1)
)
(get_local $7)
)
)
(i32.const 1)
)
(i32.const 0)
)
(get_local $8)
(i32.eq
@ -2413,34 +2404,28 @@
(if
(i32.and
(if (result i32)
(i32.ne
(tee_local $8
(i32.and
(if (result i32)
(i32.ne
(tee_local $8
(i32.eq
(i32.shl
(get_local $3)
(i32.const 1)
)
(i32.const 0)
)
(tee_local $8
(i32.and
(if (result i32)
(tee_local $8
(i32.eq
(i32.shl
(get_local $3)
(i32.const 1)
)
(i32.const 0)
)
(get_local $8)
(f32.ne
(tee_local $7
(get_local $1)
)
(get_local $7)
)
)
(i32.const 1)
(get_local $8)
(f32.ne
(tee_local $7
(get_local $1)
)
(get_local $7)
)
)
(i32.const 1)
)
(i32.const 0)
)
(get_local $8)
(i32.eq
@ -4161,10 +4146,7 @@
)
(drop
(if (result i32)
(i32.ne
(i32.const 0)
(i32.const 0)
)
(i32.const 0)
(unreachable)
(i32.const 0)
)
@ -4181,10 +4163,7 @@
)
(drop
(if (result i32)
(i32.ne
(i32.const 1)
(i32.const 0)
)
(i32.const 1)
(i32.const 1)
(unreachable)
)
@ -4201,18 +4180,12 @@
)
(drop
(if (result i32)
(i32.ne
(tee_local $0
(if (result i32)
(i32.ne
(i32.const 1)
(i32.const 0)
)
(i32.const 2)
(i32.const 1)
)
(tee_local $0
(if (result i32)
(i32.const 1)
(i32.const 2)
(i32.const 1)
)
(i32.const 0)
)
(get_local $0)
(unreachable)
@ -4239,10 +4212,7 @@
)
(set_global $logical/i
(if (result i32)
(i32.ne
(i32.const 1)
(i32.const 0)
)
(i32.const 1)
(i32.const 2)
(i32.const 1)
)
@ -4266,10 +4236,7 @@
)
(set_global $logical/i
(if (result i32)
(i32.ne
(i32.const 0)
(i32.const 0)
)
(i32.const 0)
(i32.const 0)
(i32.const 1)
)

View File

@ -61,14 +61,11 @@
(if
(i32.and
(if (result i32)
(i32.ne
(tee_local $4
(i32.gt_u
(get_local $2)
(get_local $3)
)
(tee_local $4
(i32.gt_u
(get_local $2)
(get_local $3)
)
(i32.const 0)
)
(i32.lt_s
(grow_memory
@ -476,10 +473,7 @@
(loop $continue|0
(if
(if (result i32)
(i32.ne
(get_local $2)
(i32.const 0)
)
(get_local $2)
(i32.and
(get_local $1)
(i32.const 3)
@ -2279,17 +2273,14 @@
(if
(i32.and
(if (result i32)
(i32.ne
(tee_local $3
(i32.le_u
(i32.add
(get_local $1)
(get_local $2)
)
(get_local $0)
(tee_local $3
(i32.le_u
(i32.add
(get_local $1)
(get_local $2)
)
(get_local $0)
)
(i32.const 0)
)
(get_local $3)
(i32.le_u
@ -2607,10 +2598,7 @@
(loop $continue|0
(if
(if (result i32)
(i32.ne
(get_local $2)
(i32.const 0)
)
(get_local $2)
(i32.eq
(i32.load8_u
(get_local $0)

View File

@ -62,14 +62,11 @@
(if
(i32.and
(if (result i32)
(i32.ne
(tee_local $4
(i32.gt_u
(get_local $2)
(get_local $3)
)
(tee_local $4
(i32.gt_u
(get_local $2)
(get_local $3)
)
(i32.const 0)
)
(i32.lt_s
(grow_memory
@ -135,10 +132,7 @@
(loop $continue|0
(if
(if (result i32)
(i32.ne
(get_local $2)
(i32.const 0)
)
(get_local $2)
(i32.and
(get_local $1)
(i32.const 3)
@ -1938,17 +1932,14 @@
(if
(i32.and
(if (result i32)
(i32.ne
(tee_local $3
(i32.le_u
(i32.add
(get_local $1)
(get_local $2)
)
(get_local $0)
(tee_local $3
(i32.le_u
(i32.add
(get_local $1)
(get_local $2)
)
(get_local $0)
)
(i32.const 0)
)
(get_local $3)
(i32.le_u

View File

@ -53,14 +53,11 @@
(if
(i32.and
(if (result i32)
(i32.ne
(tee_local $4
(i32.gt_u
(get_local $2)
(get_local $3)
)
(tee_local $4
(i32.gt_u
(get_local $2)
(get_local $3)
)
(i32.const 0)
)
(i32.lt_s
(grow_memory

View File

@ -16,29 +16,23 @@
(i32.eqz
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.eq
(i32.const 2)
(i32.const 1)
)
)
(i32.const 0)
)
(get_local $1)
(tee_local $1
(i32.and
(if (result i32)
(tee_local $1
(i32.eq
(i32.const 2)
(i32.const 2)
(i32.const 1)
)
)
(i32.const 1)
(get_local $1)
(i32.eq
(i32.const 2)
(i32.const 2)
)
)
(i32.const 1)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
@ -62,14 +56,11 @@
(if
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.eq
(i32.const 2)
(i32.const 2)
)
(tee_local $1
(i32.eq
(i32.const 2)
(i32.const 2)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
@ -137,44 +128,35 @@
(i32.eqz
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.eq
(i32.const 2)
(i32.const 1)
)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
(i32.const 2)
(i32.const 2)
)
(tee_local $1
(i32.and
(if (result i32)
(tee_local $1
(i32.and
(if (result i32)
(tee_local $1
(i32.eq
(i32.const 2)
(i32.const 1)
)
(i32.const 1)
)
(get_local $1)
(i32.eq
(i32.const 2)
(i32.const 2)
)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
(i32.const 2)
(i32.const 4)
(i32.const 1)
)
)
(i32.const 1)
(get_local $1)
(i32.eq
(i32.const 2)
(i32.const 4)
)
)
(i32.const 1)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
@ -311,29 +293,23 @@
(i32.eqz
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.eq
(i32.const 2)
(i32.const 1)
)
)
(i32.const 0)
)
(get_local $1)
(tee_local $1
(i32.and
(if (result i32)
(tee_local $1
(i32.eq
(i32.const 2)
(i32.const 2)
(i32.const 1)
)
)
(i32.const 1)
(get_local $1)
(i32.eq
(i32.const 2)
(i32.const 2)
)
)
(i32.const 1)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
@ -357,14 +333,11 @@
(if
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.eq
(i32.const 2)
(i32.const 2)
)
(tee_local $1
(i32.eq
(i32.const 2)
(i32.const 2)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
@ -456,44 +429,35 @@
(i32.eqz
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.eq
(i32.const 2)
(i32.const 1)
)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
(i32.const 2)
(i32.const 2)
)
(tee_local $1
(i32.and
(if (result i32)
(tee_local $1
(i32.and
(if (result i32)
(tee_local $1
(i32.eq
(i32.const 2)
(i32.const 1)
)
(i32.const 1)
)
(get_local $1)
(i32.eq
(i32.const 2)
(i32.const 2)
)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
(i32.const 2)
(i32.const 4)
(i32.const 1)
)
)
(i32.const 1)
(get_local $1)
(i32.eq
(i32.const 2)
(i32.const 4)
)
)
(i32.const 1)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
@ -636,29 +600,23 @@
(i32.eqz
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.eq
(i32.const 4)
(i32.const 1)
)
)
(i32.const 0)
)
(get_local $1)
(tee_local $1
(i32.and
(if (result i32)
(tee_local $1
(i32.eq
(i32.const 4)
(i32.const 2)
(i32.const 1)
)
)
(i32.const 1)
(get_local $1)
(i32.eq
(i32.const 4)
(i32.const 2)
)
)
(i32.const 1)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
@ -682,14 +640,11 @@
(if
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.eq
(i32.const 4)
(i32.const 2)
)
(tee_local $1
(i32.eq
(i32.const 4)
(i32.const 2)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
@ -737,44 +692,35 @@
(i32.eqz
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.eq
(i32.const 4)
(i32.const 1)
)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
(i32.const 4)
(i32.const 2)
)
(tee_local $1
(i32.and
(if (result i32)
(tee_local $1
(i32.and
(if (result i32)
(tee_local $1
(i32.eq
(i32.const 4)
(i32.const 1)
)
(i32.const 1)
)
(get_local $1)
(i32.eq
(i32.const 4)
(i32.const 2)
)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
(i32.const 4)
(i32.const 4)
(i32.const 1)
)
)
(i32.const 1)
(get_local $1)
(i32.eq
(i32.const 4)
(i32.const 4)
)
)
(i32.const 1)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
@ -905,29 +851,23 @@
(i32.eqz
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.eq
(i32.const 4)
(i32.const 1)
)
)
(i32.const 0)
)
(get_local $1)
(tee_local $1
(i32.and
(if (result i32)
(tee_local $1
(i32.eq
(i32.const 4)
(i32.const 2)
(i32.const 1)
)
)
(i32.const 1)
(get_local $1)
(i32.eq
(i32.const 4)
(i32.const 2)
)
)
(i32.const 1)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
@ -951,14 +891,11 @@
(if
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.eq
(i32.const 4)
(i32.const 2)
)
(tee_local $1
(i32.eq
(i32.const 4)
(i32.const 2)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
@ -1008,44 +945,35 @@
(i32.eqz
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.eq
(i32.const 4)
(i32.const 1)
)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
(i32.const 4)
(i32.const 2)
)
(tee_local $1
(i32.and
(if (result i32)
(tee_local $1
(i32.and
(if (result i32)
(tee_local $1
(i32.eq
(i32.const 4)
(i32.const 1)
)
(i32.const 1)
)
(get_local $1)
(i32.eq
(i32.const 4)
(i32.const 2)
)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
(i32.const 4)
(i32.const 4)
(i32.const 1)
)
)
(i32.const 1)
(get_local $1)
(i32.eq
(i32.const 4)
(i32.const 4)
)
)
(i32.const 1)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
@ -1176,29 +1104,23 @@
(i32.eqz
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.eq
(i32.const 8)
(i32.const 1)
)
)
(i32.const 0)
)
(get_local $1)
(tee_local $1
(i32.and
(if (result i32)
(tee_local $1
(i32.eq
(i32.const 8)
(i32.const 2)
(i32.const 1)
)
)
(i32.const 1)
(get_local $1)
(i32.eq
(i32.const 8)
(i32.const 2)
)
)
(i32.const 1)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
@ -1222,14 +1144,11 @@
(if
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.eq
(i32.const 8)
(i32.const 2)
)
(tee_local $1
(i32.eq
(i32.const 8)
(i32.const 2)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
@ -1277,44 +1196,35 @@
(i32.eqz
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.eq
(i32.const 8)
(i32.const 1)
)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
(i32.const 8)
(i32.const 2)
)
(tee_local $1
(i32.and
(if (result i32)
(tee_local $1
(i32.and
(if (result i32)
(tee_local $1
(i32.eq
(i32.const 8)
(i32.const 1)
)
(i32.const 1)
)
(get_local $1)
(i32.eq
(i32.const 8)
(i32.const 2)
)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
(i32.const 8)
(i32.const 4)
(i32.const 1)
)
)
(i32.const 1)
(get_local $1)
(i32.eq
(i32.const 8)
(i32.const 4)
)
)
(i32.const 1)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
@ -1445,29 +1355,23 @@
(i32.eqz
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.eq
(i32.const 8)
(i32.const 1)
)
)
(i32.const 0)
)
(get_local $1)
(tee_local $1
(i32.and
(if (result i32)
(tee_local $1
(i32.eq
(i32.const 8)
(i32.const 2)
(i32.const 1)
)
)
(i32.const 1)
(get_local $1)
(i32.eq
(i32.const 8)
(i32.const 2)
)
)
(i32.const 1)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
@ -1491,14 +1395,11 @@
(if
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.eq
(i32.const 8)
(i32.const 2)
)
(tee_local $1
(i32.eq
(i32.const 8)
(i32.const 2)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
@ -1546,44 +1447,35 @@
(i32.eqz
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.eq
(i32.const 8)
(i32.const 1)
)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
(i32.const 8)
(i32.const 2)
)
(tee_local $1
(i32.and
(if (result i32)
(tee_local $1
(i32.and
(if (result i32)
(tee_local $1
(i32.eq
(i32.const 8)
(i32.const 1)
)
(i32.const 1)
)
(get_local $1)
(i32.eq
(i32.const 8)
(i32.const 2)
)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
(i32.const 8)
(i32.const 4)
(i32.const 1)
)
)
(i32.const 1)
(get_local $1)
(i32.eq
(i32.const 8)
(i32.const 4)
)
)
(i32.const 1)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
@ -1714,29 +1606,23 @@
(i32.eqz
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.eq
(i32.const 4)
(i32.const 1)
)
)
(i32.const 0)
)
(get_local $1)
(tee_local $1
(i32.and
(if (result i32)
(tee_local $1
(i32.eq
(i32.const 4)
(i32.const 2)
(i32.const 1)
)
)
(i32.const 1)
(get_local $1)
(i32.eq
(i32.const 4)
(i32.const 2)
)
)
(i32.const 1)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
@ -1760,14 +1646,11 @@
(if
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.eq
(i32.const 4)
(i32.const 2)
)
(tee_local $1
(i32.eq
(i32.const 4)
(i32.const 2)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
@ -1815,44 +1698,35 @@
(i32.eqz
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.eq
(i32.const 4)
(i32.const 1)
)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
(i32.const 4)
(i32.const 2)
)
(tee_local $1
(i32.and
(if (result i32)
(tee_local $1
(i32.and
(if (result i32)
(tee_local $1
(i32.eq
(i32.const 4)
(i32.const 1)
)
(i32.const 1)
)
(get_local $1)
(i32.eq
(i32.const 4)
(i32.const 2)
)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
(i32.const 4)
(i32.const 4)
(i32.const 1)
)
)
(i32.const 1)
(get_local $1)
(i32.eq
(i32.const 4)
(i32.const 4)
)
)
(i32.const 1)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
@ -1983,29 +1857,23 @@
(i32.eqz
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.eq
(i32.const 4)
(i32.const 1)
)
)
(i32.const 0)
)
(get_local $1)
(tee_local $1
(i32.and
(if (result i32)
(tee_local $1
(i32.eq
(i32.const 4)
(i32.const 2)
(i32.const 1)
)
)
(i32.const 1)
(get_local $1)
(i32.eq
(i32.const 4)
(i32.const 2)
)
)
(i32.const 1)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
@ -2029,14 +1897,11 @@
(if
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.eq
(i32.const 4)
(i32.const 2)
)
(tee_local $1
(i32.eq
(i32.const 4)
(i32.const 2)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
@ -2084,44 +1949,35 @@
(i32.eqz
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.and
(if (result i32)
(i32.ne
(tee_local $1
(i32.eq
(i32.const 4)
(i32.const 1)
)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
(i32.const 4)
(i32.const 2)
)
(tee_local $1
(i32.and
(if (result i32)
(tee_local $1
(i32.and
(if (result i32)
(tee_local $1
(i32.eq
(i32.const 4)
(i32.const 1)
)
(i32.const 1)
)
(get_local $1)
(i32.eq
(i32.const 4)
(i32.const 2)
)
)
(i32.const 0)
)
(get_local $1)
(i32.eq
(i32.const 4)
(i32.const 4)
(i32.const 1)
)
)
(i32.const 1)
(get_local $1)
(i32.eq
(i32.const 4)
(i32.const 4)
)
)
(i32.const 1)
)
(i32.const 0)
)
(get_local $1)
(i32.eq

View File

@ -2193,9 +2193,7 @@
(get_local $2)
(i32.const 1)
)
(i32.load offset=8
(get_local $0)
)
(get_local $3)
)
(call "$(lib)/memory/move_memory"
(i32.add
@ -2221,9 +2219,7 @@
)
(i32.sub
(i32.sub
(i32.load offset=8
(get_local $0)
)
(get_local $3)
(get_local $2)
)
(i32.const 1)

View File

@ -59,14 +59,11 @@
(if
(i32.and
(if (result i32)
(i32.ne
(tee_local $4
(i32.gt_u
(get_local $2)
(get_local $3)
)
(tee_local $4
(i32.gt_u
(get_local $2)
(get_local $3)
)
(i32.const 0)
)
(i32.lt_s
(grow_memory
@ -132,10 +129,7 @@
(loop $continue|0
(if
(if (result i32)
(i32.ne
(get_local $2)
(i32.const 0)
)
(get_local $2)
(i32.and
(get_local $1)
(i32.const 3)
@ -1935,17 +1929,14 @@
(if
(i32.and
(if (result i32)
(i32.ne
(tee_local $3
(i32.le_u
(i32.add
(get_local $1)
(get_local $2)
)
(get_local $0)
(tee_local $3
(i32.le_u
(i32.add
(get_local $1)
(get_local $2)
)
(get_local $0)
)
(i32.const 0)
)
(get_local $3)
(i32.le_u
@ -2506,9 +2497,7 @@
(get_local $2)
(i32.const 1)
)
(i32.load offset=8
(get_local $0)
)
(get_local $3)
)
(call "$(lib)/memory/move_memory"
(i32.add
@ -2534,9 +2523,7 @@
)
(i32.sub
(i32.sub
(i32.load offset=8
(get_local $0)
)
(get_local $3)
(get_local $2)
)
(i32.const 1)

View File

@ -114,10 +114,7 @@
(loop $continue|0
(if
(if (result i32)
(i32.ne
(get_local $2)
(i32.const 0)
)
(get_local $2)
(i32.eq
(i32.load8_u
(get_local $0)
@ -635,14 +632,11 @@
(if
(i32.and
(if (result i32)
(i32.ne
(tee_local $6
(i32.eq
(get_local $4)
(i32.const 48)
)
(tee_local $6
(i32.eq
(get_local $4)
(i32.const 48)
)
(i32.const 0)
)
(i32.gt_s
(get_local $2)
@ -771,14 +765,11 @@
(if
(i32.and
(if (result i32)
(i32.ne
(tee_local $6
(i32.lt_s
(get_local $1)
(i32.const 2)
)
(tee_local $6
(i32.lt_s
(get_local $1)
(i32.const 2)
)
(i32.const 0)
)
(get_local $6)
(i32.gt_s
@ -821,14 +812,11 @@
(if
(i32.and
(if (result i32)
(i32.ne
(tee_local $6
(i32.ge_s
(get_local $4)
(i32.const 48)
)
(tee_local $6
(i32.ge_s
(get_local $4)
(i32.const 48)
)
(i32.const 0)
)
(i32.le_s
(get_local $4)
@ -847,14 +835,11 @@
(if
(i32.and
(if (result i32)
(i32.ne
(tee_local $6
(i32.ge_s
(get_local $4)
(i32.const 65)
)
(tee_local $6
(i32.ge_s
(get_local $4)
(i32.const 65)
)
(i32.const 0)
)
(i32.le_s
(get_local $4)
@ -876,14 +861,11 @@
(if
(i32.and
(if (result i32)
(i32.ne
(tee_local $6
(i32.ge_s
(get_local $4)
(i32.const 97)
)
(tee_local $6
(i32.ge_s
(get_local $4)
(i32.const 97)
)
(i32.const 0)
)
(i32.le_s
(get_local $4)
@ -1119,14 +1101,11 @@
(if
(i32.and
(if (result i32)
(i32.ne
(tee_local $6
(i32.eq
(get_local $3)
(i32.const 69)
)
(tee_local $6
(i32.eq
(get_local $3)
(i32.const 69)
)
(i32.const 0)
)
(get_local $6)
(i32.eq

View File

@ -1,327 +0,0 @@
(module
(type $ii (func (param i32) (result i32)))
(type $iiiiv (func (param i32 i32 i32 i32)))
(type $iiv (func (param i32 i32)))
(type $iiiv (func (param i32 i32 i32)))
(type $iv (func (param i32)))
(type $v (func))
(import "env" "abort" (func $abort (param i32 i32 i32 i32)))
(memory $0 1)
(data (i32.const 4) "\07\00\00\00t\00l\00s\00f\00.\00t\00s")
(export "control$construct" (func $tlsf/control$construct))
(export "memory" (memory $0))
(start $start)
(func $tlsf/fls (; 1 ;) (type $ii) (param $0 i32) (result i32)
(select
(i32.sub
(i32.const 31)
(i32.clz
(get_local $0)
)
)
(i32.const -1)
(get_local $0)
)
)
(func $tlsf/ffs (; 2 ;) (type $ii) (param $0 i32) (result i32)
(select
(i32.ctz
(get_local $0)
)
(i32.const -1)
(get_local $0)
)
)
(func $tlsf/block$set_next_free (; 3 ;) (type $iiv) (param $0 i32) (param $1 i32)
(i32.store
(i32.add
(get_local $0)
(i32.const 8)
)
(get_local $1)
)
)
(func $tlsf/block$set_prev_free (; 4 ;) (type $iiv) (param $0 i32) (param $1 i32)
(i32.store
(i32.add
(get_local $0)
(i32.const 12)
)
(get_local $1)
)
)
(func $tlsf/control$set_fl_bitmap (; 5 ;) (type $iiv) (param $0 i32) (param $1 i32)
(i32.store
(i32.add
(get_local $0)
(i32.const 16)
)
(get_local $1)
)
)
(func $tlsf/control$set_sl_bitmap (; 6 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32)
(if
(i32.ge_u
(get_local $1)
(i32.const 23)
)
(block
(call $abort
(i32.const 0)
(i32.const 4)
(i32.const 162)
(i32.const 2)
)
(unreachable)
)
)
(i32.store
(i32.add
(i32.add
(get_local $0)
(i32.const 20)
)
(i32.shl
(get_local $1)
(i32.const 2)
)
)
(get_local $2)
)
)
(func $tlsf/control$set_block (; 7 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(if
(i32.ge_u
(get_local $1)
(i32.const 23)
)
(block
(call $abort
(i32.const 0)
(i32.const 4)
(i32.const 173)
(i32.const 2)
)
(unreachable)
)
)
(if
(i32.ge_u
(get_local $2)
(i32.const 32)
)
(block
(call $abort
(i32.const 0)
(i32.const 4)
(i32.const 174)
(i32.const 2)
)
(unreachable)
)
)
(i32.store
(i32.add
(i32.add
(get_local $0)
(i32.const 112)
)
(i32.shl
(i32.add
(i32.shl
(get_local $1)
(i32.const 5)
)
(get_local $2)
)
(i32.const 2)
)
)
(get_local $3)
)
)
(func $tlsf/control$construct (; 8 ;) (type $iv) (param $0 i32)
(local $1 i32)
(local $2 i32)
(call $tlsf/block$set_next_free
(get_local $0)
(get_local $0)
)
(call $tlsf/block$set_prev_free
(get_local $0)
(get_local $0)
)
(call $tlsf/control$set_fl_bitmap
(get_local $0)
(i32.const 0)
)
(loop $continue|0
(if
(i32.lt_u
(get_local $1)
(i32.const 23)
)
(block
(call $tlsf/control$set_sl_bitmap
(get_local $0)
(get_local $1)
(i32.const 0)
)
(set_local $2
(i32.const 0)
)
(loop $continue|1
(if
(i32.lt_u
(get_local $2)
(i32.const 32)
)
(block
(call $tlsf/control$set_block
(get_local $0)
(get_local $1)
(get_local $2)
(get_local $0)
)
(set_local $2
(i32.add
(get_local $2)
(i32.const 1)
)
)
(br $continue|1)
)
)
)
(set_local $1
(i32.add
(get_local $1)
(i32.const 1)
)
)
(br $continue|0)
)
)
)
)
(func $start (; 9 ;) (type $v)
(if
(i32.ne
(call $tlsf/fls
(i32.const 0)
)
(i32.const -1)
)
(block
(call $abort
(i32.const 0)
(i32.const 4)
(i32.const 10)
(i32.const 0)
)
(unreachable)
)
)
(if
(call $tlsf/fls
(i32.const 1)
)
(block
(call $abort
(i32.const 0)
(i32.const 4)
(i32.const 11)
(i32.const 0)
)
(unreachable)
)
)
(if
(i32.ne
(call $tlsf/fls
(i32.const -2147483640)
)
(i32.const 31)
)
(block
(call $abort
(i32.const 0)
(i32.const 4)
(i32.const 12)
(i32.const 0)
)
(unreachable)
)
)
(if
(i32.ne
(call $tlsf/fls
(i32.const 2147483647)
)
(i32.const 30)
)
(block
(call $abort
(i32.const 0)
(i32.const 4)
(i32.const 13)
(i32.const 0)
)
(unreachable)
)
)
(if
(i32.ne
(call $tlsf/ffs
(i32.const 0)
)
(i32.const -1)
)
(block
(call $abort
(i32.const 0)
(i32.const 4)
(i32.const 20)
(i32.const 0)
)
(unreachable)
)
)
(if
(call $tlsf/ffs
(i32.const 1)
)
(block
(call $abort
(i32.const 0)
(i32.const 4)
(i32.const 21)
(i32.const 0)
)
(unreachable)
)
)
(if
(i32.ne
(call $tlsf/ffs
(i32.const -2147483648)
)
(i32.const 31)
)
(block
(call $abort
(i32.const 0)
(i32.const 4)
(i32.const 22)
(i32.const 0)
)
(unreachable)
)
)
(call $tlsf/control$construct
(i32.load
(i32.const 4)
)
)
)
)

View File

@ -1,190 +0,0 @@
// An unfinished implementation of tlsf in low-level AssemblyScript.
// Useful as a compiler test in this state, but nothing more.
// based upon: https://github.com/mattconte/tlsf/blob/master/tlsf.c (BSD)
/** Finds the index of the least bit set. */
function fls(word: u32): i32 {
return !word ? -1: 31 - clz<i32>(word);
}
assert(fls(0) == -1);
assert(fls(1) == 0);
assert(fls(0x80000008) == 31);
assert(fls(0x7FFFFFFF) == 30);
/** Finds the index of the first bit set. */
function ffs(word: u32): i32 {
return !word ? -1 : ctz<i32>(word);
}
assert(ffs(0) == -1);
assert(ffs(1) == 0);
assert(ffs(0x80000000) == 31);
// Align allocated blocks to 8 bytes so that any native type is aligned
const ALIGN_SIZE_LOG2: i32 = 3;
const ALIGN_SIZE: i32 = 1 << ALIGN_SIZE_LOG2;
assert(ALIGN_SIZE == 8);
// Define bitmap constants
const SL_INDEX_COUNT_LOG2: i32 = 5;
const FL_INDEX_MAX: i32 = 30;
const SL_INDEX_COUNT: i32 = 1 << SL_INDEX_COUNT_LOG2;
const FL_INDEX_SHIFT: i32 = SL_INDEX_COUNT_LOG2 + ALIGN_SIZE_LOG2;
const FL_INDEX_COUNT: i32 = FL_INDEX_MAX - FL_INDEX_SHIFT + 1;
const SMALL_BLOCK_SIZE: i32 = 1 << FL_INDEX_SHIFT;
// struct block_header_t {
// struct block_header_t* prev_phys_block;
// size_t tagged_size;
// struct block_header_t* next_free;
// struct block_header_t* prev_free;
// }
const BLOCK$PREV_PHYS_BLOCK_OFFSET: usize = 0;
const BLOCK$TAGGED_SIZE_OFFSET: usize = BLOCK$PREV_PHYS_BLOCK_OFFSET + sizeof<usize>();
const BLOCK$NEXT_FREE_OFFSET: usize = BLOCK$TAGGED_SIZE_OFFSET + sizeof<usize>();
const BLOCK$PREV_FREE_OFFSET: usize = BLOCK$NEXT_FREE_OFFSET + sizeof<usize>();
const BLOCK$SIZE: usize = BLOCK$PREV_FREE_OFFSET + sizeof<usize>();
const BLOCK_HEADER_FREE_BIT: u32 = 1 << 0;
const BLOCK_HEADER_PREV_FREE_BIT: u32 = 1 << 1;
const BLOCK_OVERHEAD: usize = sizeof<usize>();
const BLOCK_START_OFFSET: usize = BLOCK$TAGGED_SIZE_OFFSET + sizeof<usize>();
const BLOCK_SIZE_MIN: usize = BLOCK$SIZE - BLOCK_OVERHEAD;
const BLOCK_SIZE_MAX: usize = 1 << (<usize>FL_INDEX_MAX);
function block$get_prev_phys_block(block: usize): usize {
return load<usize>(block + BLOCK$PREV_PHYS_BLOCK_OFFSET);
}
function block$set_prev_phys_block(block: usize, value: usize): void {
store<usize>(block + BLOCK$PREV_PHYS_BLOCK_OFFSET, value);
}
function block$get_tagged_size(block: usize): usize {
return load<usize>(block + BLOCK$TAGGED_SIZE_OFFSET);
}
function block$set_tagged_size(block: usize, value: usize): void {
store<usize>(block + BLOCK$TAGGED_SIZE_OFFSET, value);
}
function block_size(block: usize): usize {
return block$get_tagged_size(block) & ~(BLOCK_HEADER_FREE_BIT | BLOCK_HEADER_PREV_FREE_BIT);
}
function block_set_size(block: usize, value: usize): void {
store<usize>(block + BLOCK$TAGGED_SIZE_OFFSET, value | (block$get_tagged_size(block) & (BLOCK_HEADER_FREE_BIT | BLOCK_HEADER_PREV_FREE_BIT)));
}
function block$get_next_free(block: usize): usize {
return load<usize>(block + BLOCK$NEXT_FREE_OFFSET);
}
function block$set_next_free(block: usize, value: usize): void {
store<usize>(block + BLOCK$NEXT_FREE_OFFSET, value);
}
function block$get_prev_free(block: usize): usize {
return load<usize>(block + BLOCK$PREV_FREE_OFFSET);
}
function block$set_prev_free(block: usize, value: usize): void {
store<usize>(block + BLOCK$PREV_FREE_OFFSET, value);
}
function block_is_last(block: usize): bool {
return block_size(block) == 0;
}
function block_is_free(block: usize): bool {
return (block$get_tagged_size(block) & BLOCK_HEADER_FREE_BIT) != 0;
}
function block_set_free(block: usize): void {
store<usize>(block + BLOCK$TAGGED_SIZE_OFFSET, block$get_tagged_size(block) | BLOCK_HEADER_FREE_BIT);
}
function block_set_used(block: usize): void {
store<usize>(block + BLOCK$TAGGED_SIZE_OFFSET, block$get_tagged_size(block) & ~BLOCK_HEADER_FREE_BIT);
}
function block_is_prev_free(block: usize): bool {
return (block$get_tagged_size(block) & BLOCK_HEADER_PREV_FREE_BIT) != 0;
}
function block_set_prev_free(block: usize): void {
store<usize>(block + BLOCK$TAGGED_SIZE_OFFSET, block$get_tagged_size(block) | BLOCK_HEADER_PREV_FREE_BIT);
}
function block_set_prev_used(block: usize): void {
store<usize>(block + BLOCK$TAGGED_SIZE_OFFSET, block$get_tagged_size(block) & ~BLOCK_HEADER_PREV_FREE_BIT);
}
function block_from_ptr(ptr: usize): usize {
return ptr - BLOCK_START_OFFSET;
}
function block_to_ptr(block: usize): usize {
return block + BLOCK_START_OFFSET;
}
// struct control_t {
// block_header_t block_null;
// unsigned int fl_bitmap;
// unsigned int sl_bitmap[FL_INDEX_COUNT];
// block_header_t* blocks[FL_INDEX_COUNT][SL_INDEX_COUNT];
// }
const CONTROL$FL_BITMAP_OFFSET: usize = BLOCK$SIZE;
const CONTROL$SL_BITMAP_OFFSET: usize = CONTROL$FL_BITMAP_OFFSET + sizeof<u32>();
const CONTROL$BLOCKS_OFFSET: usize = CONTROL$SL_BITMAP_OFFSET + FL_INDEX_COUNT * sizeof<u32>();
const CONTROL$SIZE: usize = CONTROL$BLOCKS_OFFSET + FL_INDEX_COUNT * SL_INDEX_COUNT * sizeof<u32>();
function control$get_fl_bitmap(ptr: usize): u32 {
return load<u32>(ptr + CONTROL$FL_BITMAP_OFFSET);
}
function control$set_fl_bitmap(ptr: usize, value: u32): void {
store<u32>(ptr + CONTROL$FL_BITMAP_OFFSET, value);
}
function control$get_sl_bitmap(ptr: usize, flIndex: usize): u32 {
assert(flIndex < FL_INDEX_COUNT);
return load<u32>(ptr + CONTROL$SL_BITMAP_OFFSET + flIndex * sizeof<u32>());
}
function control$set_sl_bitmap(ptr: usize, flIndex: usize, value: u32): void {
assert(flIndex < FL_INDEX_COUNT);
store<u32>(ptr + CONTROL$SL_BITMAP_OFFSET + flIndex * sizeof<u32>(), value);
}
function control$get_block(ptr: usize, flIndex: usize, slIndex: usize): usize {
assert(flIndex < FL_INDEX_COUNT);
assert(slIndex < SL_INDEX_COUNT);
return load<usize>(ptr + CONTROL$BLOCKS_OFFSET + (flIndex * SL_INDEX_COUNT + slIndex) * sizeof<usize>());
}
function control$set_block(ptr: usize, flIndex: usize, slIndex: usize, value: usize): void {
assert(flIndex < FL_INDEX_COUNT);
assert(slIndex < SL_INDEX_COUNT);
store<usize>(ptr + CONTROL$BLOCKS_OFFSET + (flIndex * SL_INDEX_COUNT + slIndex) * sizeof<usize>(), value);
}
/* Clear structure and point all empty lists at the null block. */
export function control$construct(ptr: usize): void {
block$set_next_free(ptr, ptr);
block$set_prev_free(ptr, ptr);
control$set_fl_bitmap(ptr, 0);
for (var flIndex: usize = 0; flIndex < FL_INDEX_COUNT; ++flIndex) {
control$set_sl_bitmap(ptr, flIndex, 0);
for (var slIndex: usize = 0; slIndex < SL_INDEX_COUNT; ++slIndex)
control$set_block(ptr, flIndex, slIndex, ptr);
}
}
control$construct(load<usize>(sizeof<usize>())); // get HEAP_OFFSET and initialize there

View File

@ -1,412 +0,0 @@
(module
(type $ii (func (param i32) (result i32)))
(type $iiiiv (func (param i32 i32 i32 i32)))
(type $i (func (result i32)))
(type $iiv (func (param i32 i32)))
(type $iiiv (func (param i32 i32 i32)))
(type $iv (func (param i32)))
(type $v (func))
(import "env" "abort" (func $abort (param i32 i32 i32 i32)))
(global $tlsf/ALIGN_SIZE_LOG2 i32 (i32.const 3))
(global $tlsf/ALIGN_SIZE i32 (i32.const 8))
(global $tlsf/SL_INDEX_COUNT_LOG2 i32 (i32.const 5))
(global $tlsf/FL_INDEX_MAX i32 (i32.const 30))
(global $tlsf/SL_INDEX_COUNT i32 (i32.const 32))
(global $tlsf/FL_INDEX_SHIFT i32 (i32.const 8))
(global $tlsf/FL_INDEX_COUNT i32 (i32.const 23))
(global $tlsf/SMALL_BLOCK_SIZE i32 (i32.const 256))
(global $tlsf/BLOCK$PREV_PHYS_BLOCK_OFFSET i32 (i32.const 0))
(global $tlsf/BLOCK$TAGGED_SIZE_OFFSET i32 (i32.const 4))
(global $tlsf/BLOCK$NEXT_FREE_OFFSET i32 (i32.const 8))
(global $tlsf/BLOCK$PREV_FREE_OFFSET i32 (i32.const 12))
(global $tlsf/BLOCK$SIZE i32 (i32.const 16))
(global $tlsf/BLOCK_HEADER_FREE_BIT i32 (i32.const 1))
(global $tlsf/BLOCK_HEADER_PREV_FREE_BIT i32 (i32.const 2))
(global $tlsf/BLOCK_OVERHEAD i32 (i32.const 4))
(global $tlsf/BLOCK_START_OFFSET i32 (i32.const 8))
(global $tlsf/BLOCK_SIZE_MIN i32 (i32.const 12))
(global $tlsf/BLOCK_SIZE_MAX i32 (i32.const 1073741824))
(global $tlsf/CONTROL$FL_BITMAP_OFFSET i32 (i32.const 16))
(global $tlsf/CONTROL$SL_BITMAP_OFFSET i32 (i32.const 20))
(global $tlsf/CONTROL$BLOCKS_OFFSET i32 (i32.const 112))
(global $tlsf/CONTROL$SIZE i32 (i32.const 3056))
(global $HEAP_BASE i32 (i32.const 24))
(memory $0 1)
(data (i32.const 4) "\07\00\00\00t\00l\00s\00f\00.\00t\00s\00")
(export "control$construct" (func $tlsf/control$construct))
(export "memory" (memory $0))
(start $start)
(func $tlsf/fls (; 1 ;) (type $ii) (param $0 i32) (result i32)
(return
(if (result i32)
(i32.eqz
(get_local $0)
)
(i32.const -1)
(i32.sub
(i32.const 31)
(i32.clz
(get_local $0)
)
)
)
)
)
(func $tlsf/ffs (; 2 ;) (type $ii) (param $0 i32) (result i32)
(return
(if (result i32)
(i32.eqz
(get_local $0)
)
(i32.const -1)
(i32.ctz
(get_local $0)
)
)
)
)
(func $tlsf/block$set_next_free (; 3 ;) (type $iiv) (param $0 i32) (param $1 i32)
(i32.store
(i32.add
(get_local $0)
(i32.const 8)
)
(get_local $1)
)
)
(func $tlsf/block$set_prev_free (; 4 ;) (type $iiv) (param $0 i32) (param $1 i32)
(i32.store
(i32.add
(get_local $0)
(i32.const 12)
)
(get_local $1)
)
)
(func $tlsf/control$set_fl_bitmap (; 5 ;) (type $iiv) (param $0 i32) (param $1 i32)
(i32.store
(i32.add
(get_local $0)
(i32.const 16)
)
(get_local $1)
)
)
(func $tlsf/control$set_sl_bitmap (; 6 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32)
(if
(i32.eqz
(i32.lt_u
(get_local $1)
(i32.const 23)
)
)
(block
(call $abort
(i32.const 0)
(i32.const 4)
(i32.const 162)
(i32.const 2)
)
(unreachable)
)
)
(i32.store
(i32.add
(i32.add
(get_local $0)
(i32.const 20)
)
(i32.mul
(get_local $1)
(i32.const 4)
)
)
(get_local $2)
)
)
(func $tlsf/control$set_block (; 7 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(if
(i32.eqz
(i32.lt_u
(get_local $1)
(i32.const 23)
)
)
(block
(call $abort
(i32.const 0)
(i32.const 4)
(i32.const 173)
(i32.const 2)
)
(unreachable)
)
)
(if
(i32.eqz
(i32.lt_u
(get_local $2)
(i32.const 32)
)
)
(block
(call $abort
(i32.const 0)
(i32.const 4)
(i32.const 174)
(i32.const 2)
)
(unreachable)
)
)
(i32.store
(i32.add
(i32.add
(get_local $0)
(i32.const 112)
)
(i32.mul
(i32.add
(i32.mul
(get_local $1)
(i32.const 32)
)
(get_local $2)
)
(i32.const 4)
)
)
(get_local $3)
)
)
(func $tlsf/control$construct (; 8 ;) (type $iv) (param $0 i32)
(local $1 i32)
(local $2 i32)
(call $tlsf/block$set_next_free
(get_local $0)
(get_local $0)
)
(call $tlsf/block$set_prev_free
(get_local $0)
(get_local $0)
)
(call $tlsf/control$set_fl_bitmap
(get_local $0)
(i32.const 0)
)
(block $break|0
(set_local $1
(i32.const 0)
)
(loop $continue|0
(if
(i32.lt_u
(get_local $1)
(i32.const 23)
)
(block
(block
(call $tlsf/control$set_sl_bitmap
(get_local $0)
(get_local $1)
(i32.const 0)
)
(block $break|1
(set_local $2
(i32.const 0)
)
(loop $continue|1
(if
(i32.lt_u
(get_local $2)
(i32.const 32)
)
(block
(call $tlsf/control$set_block
(get_local $0)
(get_local $1)
(get_local $2)
(get_local $0)
)
(set_local $2
(i32.add
(get_local $2)
(i32.const 1)
)
)
(br $continue|1)
)
)
)
)
)
(set_local $1
(i32.add
(get_local $1)
(i32.const 1)
)
)
(br $continue|0)
)
)
)
)
)
(func $start (; 9 ;) (type $v)
(if
(i32.eqz
(i32.eq
(call $tlsf/fls
(i32.const 0)
)
(i32.const -1)
)
)
(block
(call $abort
(i32.const 0)
(i32.const 4)
(i32.const 10)
(i32.const 0)
)
(unreachable)
)
)
(if
(i32.eqz
(i32.eq
(call $tlsf/fls
(i32.const 1)
)
(i32.const 0)
)
)
(block
(call $abort
(i32.const 0)
(i32.const 4)
(i32.const 11)
(i32.const 0)
)
(unreachable)
)
)
(if
(i32.eqz
(i32.eq
(call $tlsf/fls
(i32.const -2147483640)
)
(i32.const 31)
)
)
(block
(call $abort
(i32.const 0)
(i32.const 4)
(i32.const 12)
(i32.const 0)
)
(unreachable)
)
)
(if
(i32.eqz
(i32.eq
(call $tlsf/fls
(i32.const 2147483647)
)
(i32.const 30)
)
)
(block
(call $abort
(i32.const 0)
(i32.const 4)
(i32.const 13)
(i32.const 0)
)
(unreachable)
)
)
(if
(i32.eqz
(i32.eq
(call $tlsf/ffs
(i32.const 0)
)
(i32.const -1)
)
)
(block
(call $abort
(i32.const 0)
(i32.const 4)
(i32.const 20)
(i32.const 0)
)
(unreachable)
)
)
(if
(i32.eqz
(i32.eq
(call $tlsf/ffs
(i32.const 1)
)
(i32.const 0)
)
)
(block
(call $abort
(i32.const 0)
(i32.const 4)
(i32.const 21)
(i32.const 0)
)
(unreachable)
)
)
(if
(i32.eqz
(i32.eq
(call $tlsf/ffs
(i32.const -2147483648)
)
(i32.const 31)
)
)
(block
(call $abort
(i32.const 0)
(i32.const 4)
(i32.const 22)
(i32.const 0)
)
(unreachable)
)
)
(if
(i32.eqz
(i32.eq
(i32.const 8)
(i32.const 8)
)
)
(block
(call $abort
(i32.const 0)
(i32.const 4)
(i32.const 29)
(i32.const 0)
)
(unreachable)
)
)
(call $tlsf/control$construct
(i32.load
(i32.const 4)
)
)
)
)

View File

@ -219,22 +219,19 @@
(loop $continue|3
(if
(if (result i32)
(i32.ne
(tee_local $0
(block (result i32)
(set_local $0
(get_global $while/n)
)
(set_global $while/n
(i32.sub
(get_local $0)
(i32.const 1)
)
)
(get_local $0)
(tee_local $0
(block (result i32)
(set_local $0
(get_global $while/n)
)
(set_global $while/n
(i32.sub
(get_local $0)
(i32.const 1)
)
)
(get_local $0)
)
(i32.const 0)
)
(block (result i32)
(set_global $while/m