Skip to content

Commit 4b85003

Browse files
committed
Skip inlining and emit a warning when trying to inline a function into itself
1 parent 3b0fd9a commit 4b85003

12 files changed

+52
-9
lines changed

dist/asc.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/asc.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/assemblyscript.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/assemblyscript.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/builtins.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ import {
5454
import {
5555
ReportMode
5656
} from "./resolver";
57-
import { CommonFlags } from "./common";
5857

5958
/** Compiles a call to a built-in function. */
6059
export function compileCall(
@@ -73,7 +72,7 @@ export function compileCall(
7372
ret: ExpressionRef;
7473

7574
// NOTE that some implementations below make use of the select expression where straight-forward.
76-
// whether worth or not should probably be tested once/ it's known if/how embedders handle it.
75+
// whether worth or not should probably be tested once it's known if/how embedders handle it.
7776
// search: createSelect
7877

7978
switch (prototype.internalName) {

src/compiler.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,8 @@ export class Compiler extends DiagnosticEmitter {
265265
currentFunction: Function;
266266
/** Current outer function in compilation, if compiling a function expression. */
267267
currentOuterFunction: Function | null = null;
268+
/** Current inline function in compilation. */
269+
currentInlineFunction: Function | null = null;
268270
/** Current enum in compilation. */
269271
currentEnum: Enum | null = null;
270272
/** Current type in compilation. */
@@ -5257,7 +5259,21 @@ export class Compiler extends DiagnosticEmitter {
52575259
// Inline if explicitly requested
52585260
if (inline) {
52595261
assert(!instance.is(CommonFlags.TRAMPOLINE)); // doesn't make sense
5260-
return this.compileCallInlineUnchecked(instance, argumentExpressions, reportNode, thisArg);
5262+
if (instance === this.currentInlineFunction) {
5263+
// skip inlining when trying to inline a function into itself and print a warning when
5264+
// instead compiling the function the normal way.
5265+
if (instance === this.currentFunction) {
5266+
this.warning(
5267+
DiagnosticCode.Function_0_cannot_be_inlined_into_itself,
5268+
reportNode.range, instance.internalName
5269+
);
5270+
}
5271+
} else {
5272+
this.currentInlineFunction = instance;
5273+
let ret = this.compileCallInlineUnchecked(instance, argumentExpressions, reportNode, thisArg);
5274+
this.currentInlineFunction = null;
5275+
return ret;
5276+
}
52615277
}
52625278

52635279
// Otherwise compile to just a call

src/diagnosticMessages.generated.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export enum DiagnosticCode {
2626
An_allocator_must_be_declared_to_allocate_memory_Try_importing_allocator_arena_or_allocator_tlsf = 214,
2727
Optional_parameter_must_have_an_initializer = 215,
2828
Constructor_of_class_0_must_not_require_any_arguments = 216,
29+
Function_0_cannot_be_inlined_into_itself = 217,
2930
Unterminated_string_literal = 1002,
3031
Identifier_expected = 1003,
3132
_0_expected = 1005,
@@ -142,6 +143,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
142143
case 214: return "An allocator must be declared to allocate memory. Try importing allocator/arena or allocator/tlsf.";
143144
case 215: return "Optional parameter must have an initializer.";
144145
case 216: return "Constructor of class '{0}' must not require any arguments.";
146+
case 217: return "Function '{0}' cannot be inlined into itself.";
145147
case 1002: return "Unterminated string literal.";
146148
case 1003: return "Identifier expected.";
147149
case 1005: return "'{0}' expected.";

src/diagnosticMessages.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"An allocator must be declared to allocate memory. Try importing allocator/arena or allocator/tlsf.": 214,
1919
"Optional parameter must have an initializer.": 215,
2020
"Constructor of class '{0}' must not require any arguments.": 216,
21+
"Function '{0}' cannot be inlined into itself.": 217,
2122

2223
"Unterminated string literal.": 1002,
2324
"Identifier expected.": 1003,

std/assembly/index.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,9 +304,9 @@ declare function isReference<T>(value?: any): value is object | string;
304304
declare function isString<T>(value?: any): value is string | String;
305305
/** Tests if the specified type *or* expression can be used as an array. Compiles to a constant. */
306306
declare function isArray<T>(value?: any): value is Array<any>;
307-
/** Tests if the specified expression resolves to a defined element. */
307+
/** Tests if the specified expression resolves to a defined element. Compiles to a constant. */
308308
declare function isDefined(expression: any): bool;
309-
/** Tests if the specified expression evaluates to a constant value. */
309+
/** Tests if the specified expression evaluates to a constant value. Compiles to a constant. */
310310
declare function isConstant(expression: any): bool;
311311
/** Traps if the specified value is not true-ish, otherwise returns the (non-nullable) value. */
312312
declare function assert<T>(isTrueish: T, message?: string): T & object; // any better way to model `: T != null`?
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
(module
2+
(type $v (func))
3+
(memory $0 0)
4+
(export "foo" (func $inlining-recursive/foo))
5+
(export "memory" (memory $0))
6+
(func $inlining-recursive/foo (; 0 ;) (type $v)
7+
(call $inlining-recursive/foo)
8+
)
9+
)

tests/compiler/inlining-recursive.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
@inline
2+
export function foo(): void {
3+
foo();
4+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
(module
2+
(type $v (func))
3+
(global $HEAP_BASE i32 (i32.const 8))
4+
(memory $0 0)
5+
(export "foo" (func $inlining-recursive/foo))
6+
(export "memory" (memory $0))
7+
(func $inlining-recursive/foo (; 0 ;) (type $v)
8+
(block $inlining-recursive/foo|inlined.0
9+
(call $inlining-recursive/foo)
10+
)
11+
)
12+
)

0 commit comments

Comments
 (0)