diff --git a/src/builtins.ts b/src/builtins.ts index d37045f4..3a3da135 100644 --- a/src/builtins.ts +++ b/src/builtins.ts @@ -1578,19 +1578,8 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty return arg0; } - var abort: ExpressionRef = module.createUnreachable(); - var abortPrototype = compiler.program.elements.get("abort"); - if (abortPrototype && abortPrototype.kind == ElementKind.FUNCTION_PROTOTYPE) { - var abortInstance = (abortPrototype).resolve(); - if (abortInstance && compiler.compileFunction(abortInstance)) { - abort = compiler.makeCall(abortInstance, [ - operands.length == 2 ? compiler.compileExpression(operands[1], compiler.options.usizeType) : compiler.options.usizeType.toNativeZero(module), - compiler.compileStaticString(reportNode.range.source.path), - module.createI32(reportNode.range.line), - module.createI32(reportNode.range.column) - ]); - } - } + var abort = compileAbort(compiler, operands.length == 2 ? operands[1] : null, reportNode); + compiler.currentType = type.nonNullableType; if (contextualType == Type.void) { // simplify if dropped anyway @@ -1911,3 +1900,35 @@ export function compileAllocate(compiler: Compiler, cls: Class, reportNode: Node program.error(DiagnosticCode.Cannot_find_name_0, reportNode.range, compiler.options.allocateImpl); return compiler.module.createUnreachable(); } + +/** Compiles an abort wired to the global 'abort' function if present. */ +export function compileAbort(compiler: Compiler, message: Expression | null, reportNode: Node): ExpressionRef { + var module = compiler.module; + + var abort: ExpressionRef = module.createUnreachable(); + var abortPrototype = compiler.program.elements.get("abort"); + var stringType = compiler.program.types.get("string"); + if (abortPrototype && abortPrototype.kind == ElementKind.FUNCTION_PROTOTYPE && stringType) { + var abortInstance = (abortPrototype).resolve(); + if (abortInstance) { + if (abortInstance.parameters.length != 4) { + // TODO: validate parameter types (currently becomes a validation error if invalid) + var abortDeclaration = assert((abortPrototype).declaration); + compiler.error(DiagnosticCode.Expected_0_arguments_but_got_1, abortDeclaration.name.range, "4", abortInstance.parameters.length.toString(10)); + } else if (compiler.compileFunction(abortInstance)) { + abort = module.createBlock(null, [ + compiler.makeCall(abortInstance, [ + message != null + ? compiler.compileExpression(message, stringType) + : compiler.options.usizeType.toNativeZero(module), + compiler.compileStaticString(reportNode.range.source.path), + module.createI32(reportNode.range.line), + module.createI32(reportNode.range.column) + ]), + abort + ]); + } + } + } + return abort; +} diff --git a/tests/compiler/std/abort.optimized.wast b/tests/compiler/std/abort.optimized.wast deleted file mode 100644 index 40879b89..00000000 --- a/tests/compiler/std/abort.optimized.wast +++ /dev/null @@ -1,20 +0,0 @@ -(module - (type $v (func)) - (global $std/abort/abortCalled (mut i32) (i32.const 0)) - (memory $0 1) - (data (i32.const 8) "\n\00\00\00t\00h\00i\00s\00 \00i\00s\00 \00o\00k") - (data (i32.const 32) "\0c\00\00\00s\00t\00d\00/\00a\00b\00o\00r\00t\00.\00t\00s") - (export "memory" (memory $0)) - (start $start) - (func $start (; 0 ;) (type $v) - (set_global $std/abort/abortCalled - (i32.const 1) - ) - (if - (i32.eqz - (get_global $std/abort/abortCalled) - ) - (unreachable) - ) - ) -) diff --git a/tests/compiler/std/abort.ts b/tests/compiler/std/abort.ts deleted file mode 100644 index d29a3602..00000000 --- a/tests/compiler/std/abort.ts +++ /dev/null @@ -1,11 +0,0 @@ -var abortCalled = false; - -@global -function abort(message: string | null, filename: string, line: i32, column: i32): void { - abortCalled = true; -} - -assert(false, "this is ok"); - -if (!abortCalled) - unreachable(); diff --git a/tests/compiler/std/abort.wast b/tests/compiler/std/abort.wast deleted file mode 100644 index 91e78cab..00000000 --- a/tests/compiler/std/abort.wast +++ /dev/null @@ -1,156 +0,0 @@ -(module - (type $iiiiv (func (param i32 i32 i32 i32))) - (type $v (func)) - (global $std/abort/abortCalled (mut i32) (i32.const 0)) - (global $HEAP_BASE i32 (i32.const 60)) - (memory $0 1) - (data (i32.const 8) "\n\00\00\00t\00h\00i\00s\00 \00i\00s\00 \00o\00k\00") - (data (i32.const 32) "\0c\00\00\00s\00t\00d\00/\00a\00b\00o\00r\00t\00.\00t\00s\00") - (export "memory" (memory $0)) - (start $start) - (func $std/abort/abort (; 0 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) - (set_global $std/abort/abortCalled - (i32.const 1) - ) - ) - (func $start (; 1 ;) (type $v) - (if - (i32.eqz - (i32.const 0) - ) - (call $std/abort/abort - (i32.const 8) - (i32.const 32) - (i32.const 8) - (i32.const 2) - ) - ) - (if - (i32.eqz - (get_global $std/abort/abortCalled) - ) - (unreachable) - ) - ) -) -(; -[program.elements] - GLOBAL: NaN - GLOBAL: Infinity - FUNCTION_PROTOTYPE: isNaN - FUNCTION_PROTOTYPE: isFinite - FUNCTION_PROTOTYPE: clz - FUNCTION_PROTOTYPE: ctz - FUNCTION_PROTOTYPE: popcnt - FUNCTION_PROTOTYPE: rotl - FUNCTION_PROTOTYPE: rotr - FUNCTION_PROTOTYPE: abs - FUNCTION_PROTOTYPE: max - FUNCTION_PROTOTYPE: min - FUNCTION_PROTOTYPE: ceil - FUNCTION_PROTOTYPE: floor - FUNCTION_PROTOTYPE: copysign - FUNCTION_PROTOTYPE: nearest - FUNCTION_PROTOTYPE: reinterpret - FUNCTION_PROTOTYPE: sqrt - FUNCTION_PROTOTYPE: trunc - FUNCTION_PROTOTYPE: load - FUNCTION_PROTOTYPE: store - FUNCTION_PROTOTYPE: sizeof - FUNCTION_PROTOTYPE: select - FUNCTION_PROTOTYPE: unreachable - FUNCTION_PROTOTYPE: current_memory - FUNCTION_PROTOTYPE: grow_memory - FUNCTION_PROTOTYPE: changetype - FUNCTION_PROTOTYPE: assert - FUNCTION_PROTOTYPE: i8 - FUNCTION_PROTOTYPE: i16 - FUNCTION_PROTOTYPE: i32 - FUNCTION_PROTOTYPE: i64 - FUNCTION_PROTOTYPE: u8 - FUNCTION_PROTOTYPE: u16 - FUNCTION_PROTOTYPE: u32 - FUNCTION_PROTOTYPE: u64 - FUNCTION_PROTOTYPE: bool - FUNCTION_PROTOTYPE: f32 - FUNCTION_PROTOTYPE: f64 - FUNCTION_PROTOTYPE: isize - FUNCTION_PROTOTYPE: usize - GLOBAL: HEAP_BASE - CLASS_PROTOTYPE: std:array/Array - PROPERTY: std:array/Array#length - CLASS_PROTOTYPE: Array - CLASS_PROTOTYPE: std:array/CArray - CLASS_PROTOTYPE: CArray - CLASS_PROTOTYPE: std:error/Error - CLASS_PROTOTYPE: Error - CLASS_PROTOTYPE: std:error/RangeError - CLASS_PROTOTYPE: RangeError - GLOBAL: std:heap/ALIGN_LOG2 - GLOBAL: std:heap/ALIGN_SIZE - GLOBAL: std:heap/ALIGN_MASK - GLOBAL: std:heap/HEAP_OFFSET - FUNCTION_PROTOTYPE: std:heap/allocate_memory - FUNCTION_PROTOTYPE: allocate_memory - FUNCTION_PROTOTYPE: std:heap/free_memory - FUNCTION_PROTOTYPE: free_memory - FUNCTION_PROTOTYPE: std:heap/copy_memory - FUNCTION_PROTOTYPE: std:heap/move_memory - FUNCTION_PROTOTYPE: move_memory - FUNCTION_PROTOTYPE: std:heap/set_memory - FUNCTION_PROTOTYPE: set_memory - FUNCTION_PROTOTYPE: std:heap/compare_memory - FUNCTION_PROTOTYPE: compare_memory - CLASS_PROTOTYPE: std:map/Map - CLASS_PROTOTYPE: Map - CLASS_PROTOTYPE: std:regexp/RegExp - CLASS_PROTOTYPE: RegExp - CLASS_PROTOTYPE: std:set/Set - PROPERTY: std:set/Set#size - CLASS_PROTOTYPE: Set - GLOBAL: std:string/EMPTY - GLOBAL: std:string/HEAD - FUNCTION_PROTOTYPE: std:string/allocate - CLASS_PROTOTYPE: std:string/String - CLASS_PROTOTYPE: String - FUNCTION_PROTOTYPE: std:string/isWhiteSpaceOrLineTerminator - FUNCTION_PROTOTYPE: std:string/parseInt - FUNCTION_PROTOTYPE: parseInt - FUNCTION_PROTOTYPE: std:string/parseFloat - FUNCTION_PROTOTYPE: parseFloat - GLOBAL: std/abort/abortCalled - FUNCTION_PROTOTYPE: std/abort/abort - FUNCTION_PROTOTYPE: abort -[program.exports] - CLASS_PROTOTYPE: std:array/Array - CLASS_PROTOTYPE: Array - CLASS_PROTOTYPE: std:array/CArray - CLASS_PROTOTYPE: CArray - CLASS_PROTOTYPE: std:error/Error - CLASS_PROTOTYPE: Error - CLASS_PROTOTYPE: std:error/RangeError - CLASS_PROTOTYPE: RangeError - FUNCTION_PROTOTYPE: allocate_memory - FUNCTION_PROTOTYPE: std:heap/allocate_memory - FUNCTION_PROTOTYPE: free_memory - FUNCTION_PROTOTYPE: std:heap/free_memory - FUNCTION_PROTOTYPE: move_memory - FUNCTION_PROTOTYPE: std:heap/move_memory - FUNCTION_PROTOTYPE: set_memory - FUNCTION_PROTOTYPE: std:heap/set_memory - FUNCTION_PROTOTYPE: compare_memory - FUNCTION_PROTOTYPE: std:heap/compare_memory - CLASS_PROTOTYPE: std:map/Map - CLASS_PROTOTYPE: Map - CLASS_PROTOTYPE: std:regexp/RegExp - CLASS_PROTOTYPE: RegExp - CLASS_PROTOTYPE: std:set/Set - CLASS_PROTOTYPE: Set - CLASS_PROTOTYPE: std:string/String - CLASS_PROTOTYPE: String - FUNCTION_PROTOTYPE: parseInt - FUNCTION_PROTOTYPE: std:string/parseInt - FUNCTION_PROTOTYPE: parseFloat - FUNCTION_PROTOTYPE: std:string/parseFloat - FUNCTION_PROTOTYPE: abort -;)