0e53739c39
This CL adds lint errors when 'let' bindings, arguments and labels are not used. Note that errors for 'const' bindings will be added later. In cases where arguments are actually needed to match the signature, the warning can be silenced by prefixing identifiers with "_". This might be needed for generic specializations or builtins called from TurboFan. Trying to use a variable or label that was marked with "_" results in a compilation error. Implicit arguments are not linted. They are implemented using exact string matching. Prefixing an implicit argument with "_" in a callee would break all callers as the names would no longer match. Drive-by: Fix all new lint errors in the existing Torque code. Bug: v8:7793 Change-Id: I68b3c59c76b956e9f88709e9388a40a19546ce52 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1645092 Commit-Queue: Simon Zünd <szuend@chromium.org> Reviewed-by: Tobias Tebbi <tebbi@chromium.org> Reviewed-by: Sigurd Schneider <sigurds@chromium.org> Cr-Commit-Position: refs/heads/master@{#62027}
928 lines
21 KiB
Plaintext
928 lines
21 KiB
Plaintext
// Copyright 2018 the V8 project authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
namespace test {
|
|
macro ElementsKindTestHelper1(kind: constexpr ElementsKind): bool {
|
|
if constexpr ((kind == UINT8_ELEMENTS) || (kind == UINT16_ELEMENTS)) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
macro ElementsKindTestHelper2(kind: constexpr ElementsKind): bool {
|
|
return ((kind == UINT8_ELEMENTS) || (kind == UINT16_ELEMENTS));
|
|
}
|
|
|
|
macro ElementsKindTestHelper3(kind: constexpr ElementsKind): constexpr bool {
|
|
return ((kind == UINT8_ELEMENTS) || (kind == UINT16_ELEMENTS));
|
|
}
|
|
|
|
macro LabelTestHelper1(): never
|
|
labels Label1 {
|
|
goto Label1;
|
|
}
|
|
|
|
macro LabelTestHelper2(): never
|
|
labels Label2(Smi) {
|
|
goto Label2(42);
|
|
}
|
|
|
|
macro LabelTestHelper3(): never
|
|
labels Label3(Oddball, Smi) {
|
|
goto Label3(Null, 7);
|
|
}
|
|
|
|
@export
|
|
macro TestConstexpr1() {
|
|
check(FromConstexpr<bool>(IsFastElementsKind(PACKED_SMI_ELEMENTS)));
|
|
}
|
|
|
|
@export
|
|
macro TestConstexprIf() {
|
|
check(ElementsKindTestHelper1(UINT8_ELEMENTS));
|
|
check(ElementsKindTestHelper1(UINT16_ELEMENTS));
|
|
check(!ElementsKindTestHelper1(UINT32_ELEMENTS));
|
|
}
|
|
|
|
@export
|
|
macro TestConstexprReturn() {
|
|
check(FromConstexpr<bool>(ElementsKindTestHelper3(UINT8_ELEMENTS)));
|
|
check(FromConstexpr<bool>(ElementsKindTestHelper3(UINT16_ELEMENTS)));
|
|
check(!FromConstexpr<bool>(ElementsKindTestHelper3(UINT32_ELEMENTS)));
|
|
check(FromConstexpr<bool>(!ElementsKindTestHelper3(UINT32_ELEMENTS)));
|
|
}
|
|
|
|
@export
|
|
macro TestGotoLabel(): Boolean {
|
|
try {
|
|
LabelTestHelper1() otherwise Label1;
|
|
}
|
|
label Label1 {
|
|
return True;
|
|
}
|
|
}
|
|
|
|
@export
|
|
macro TestGotoLabelWithOneParameter(): Boolean {
|
|
try {
|
|
LabelTestHelper2() otherwise Label2;
|
|
}
|
|
label Label2(smi: Smi) {
|
|
check(smi == 42);
|
|
return True;
|
|
}
|
|
}
|
|
|
|
@export
|
|
macro TestGotoLabelWithTwoParameters(): Boolean {
|
|
try {
|
|
LabelTestHelper3() otherwise Label3;
|
|
}
|
|
label Label3(o: Oddball, smi: Smi) {
|
|
check(o == Null);
|
|
check(smi == 7);
|
|
return True;
|
|
}
|
|
}
|
|
|
|
builtin GenericBuiltinTest<T: type>(_c: Context, _param: T): Object {
|
|
return Null;
|
|
}
|
|
|
|
GenericBuiltinTest<Object>(_c: Context, param: Object): Object {
|
|
return param;
|
|
}
|
|
|
|
@export
|
|
macro TestBuiltinSpecialization(c: Context) {
|
|
check(GenericBuiltinTest<Smi>(c, 0) == Null);
|
|
check(GenericBuiltinTest<Smi>(c, 1) == Null);
|
|
check(GenericBuiltinTest<Object>(c, Undefined) == Undefined);
|
|
check(GenericBuiltinTest<Object>(c, Undefined) == Undefined);
|
|
}
|
|
|
|
macro LabelTestHelper4(flag: constexpr bool): never
|
|
labels Label4, Label5 {
|
|
if constexpr (flag) {
|
|
goto Label4;
|
|
} else {
|
|
goto Label5;
|
|
}
|
|
}
|
|
|
|
macro CallLabelTestHelper4(flag: constexpr bool): bool {
|
|
try {
|
|
LabelTestHelper4(flag) otherwise Label4, Label5;
|
|
}
|
|
label Label4 {
|
|
return true;
|
|
}
|
|
label Label5 {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
@export
|
|
macro TestPartiallyUnusedLabel(): Boolean {
|
|
let r1: bool = CallLabelTestHelper4(true);
|
|
let r2: bool = CallLabelTestHelper4(false);
|
|
|
|
if (r1 && !r2) {
|
|
return True;
|
|
} else {
|
|
return False;
|
|
}
|
|
}
|
|
|
|
macro GenericMacroTest<T: type>(_param: T): Object {
|
|
return Undefined;
|
|
}
|
|
|
|
GenericMacroTest<Object>(param2: Object): Object {
|
|
return param2;
|
|
}
|
|
|
|
macro GenericMacroTestWithLabels<T: type>(_param: T): Object
|
|
labels _X {
|
|
return Undefined;
|
|
}
|
|
|
|
GenericMacroTestWithLabels<Object>(param2: Object): Object
|
|
labels Y {
|
|
return Cast<Smi>(param2) otherwise Y;
|
|
}
|
|
|
|
@export
|
|
macro TestMacroSpecialization() {
|
|
try {
|
|
const _smi0: Smi = 0;
|
|
check(GenericMacroTest<Smi>(0) == Undefined);
|
|
check(GenericMacroTest<Smi>(1) == Undefined);
|
|
check(GenericMacroTest<Object>(Null) == Null);
|
|
check(GenericMacroTest<Object>(False) == False);
|
|
check(GenericMacroTest<Object>(True) == True);
|
|
check((GenericMacroTestWithLabels<Smi>(0) otherwise Fail) == Undefined);
|
|
check((GenericMacroTestWithLabels<Smi>(0) otherwise Fail) == Undefined);
|
|
try {
|
|
GenericMacroTestWithLabels<Object>(False) otherwise Expected;
|
|
}
|
|
label Expected {}
|
|
}
|
|
label Fail {
|
|
unreachable;
|
|
}
|
|
}
|
|
|
|
builtin TestHelperPlus1(_context: Context, x: Smi): Smi {
|
|
return x + 1;
|
|
}
|
|
builtin TestHelperPlus2(_context: Context, x: Smi): Smi {
|
|
return x + 2;
|
|
}
|
|
|
|
@export
|
|
macro TestFunctionPointers(implicit context: Context)(): Boolean {
|
|
let fptr: builtin(Context, Smi) => Smi = TestHelperPlus1;
|
|
check(fptr(context, 42) == 43);
|
|
fptr = TestHelperPlus2;
|
|
check(fptr(context, 42) == 44);
|
|
return True;
|
|
}
|
|
|
|
@export
|
|
macro TestVariableRedeclaration(implicit context: Context)(): Boolean {
|
|
let _var1: int31 = FromConstexpr<bool>(42 == 0) ? 0 : 1;
|
|
let _var2: int31 = FromConstexpr<bool>(42 == 0) ? 1 : 0;
|
|
return True;
|
|
}
|
|
|
|
@export
|
|
macro TestTernaryOperator(x: Smi): Smi {
|
|
let b: bool = x < 0 ? true : false;
|
|
return b ? x - 10 : x + 100;
|
|
}
|
|
|
|
@export
|
|
macro TestFunctionPointerToGeneric(c: Context) {
|
|
let fptr1: builtin(Context, Smi) => Object = GenericBuiltinTest<Smi>;
|
|
let fptr2: builtin(Context, Object) => Object = GenericBuiltinTest<Object>;
|
|
|
|
check(fptr1(c, 0) == Null);
|
|
check(fptr1(c, 1) == Null);
|
|
check(fptr2(c, Undefined) == Undefined);
|
|
check(fptr2(c, Undefined) == Undefined);
|
|
}
|
|
|
|
type ObjectToObject = builtin(Context, Object) => Object;
|
|
@export
|
|
macro TestTypeAlias(x: ObjectToObject): BuiltinPtr {
|
|
return x;
|
|
}
|
|
|
|
@export
|
|
macro TestUnsafeCast(implicit context: Context)(n: Number): Boolean {
|
|
if (TaggedIsSmi(n)) {
|
|
let m: Smi = UnsafeCast<Smi>(n);
|
|
|
|
check(TestHelperPlus1(context, m) == 11);
|
|
return True;
|
|
}
|
|
return False;
|
|
}
|
|
|
|
@export
|
|
macro TestHexLiteral() {
|
|
check(Convert<intptr>(0xffff) + 1 == 0x10000);
|
|
check(Convert<intptr>(-0xffff) == -65535);
|
|
}
|
|
|
|
@export
|
|
macro TestLargeIntegerLiterals(implicit c: Context)() {
|
|
let _x: int32 = 0x40000000;
|
|
let _y: int32 = 0x7fffffff;
|
|
}
|
|
|
|
@export
|
|
macro TestMultilineAssert() {
|
|
let someVeryLongVariableNameThatWillCauseLineBreaks: Smi = 5;
|
|
check(
|
|
someVeryLongVariableNameThatWillCauseLineBreaks > 0 &&
|
|
someVeryLongVariableNameThatWillCauseLineBreaks < 10);
|
|
}
|
|
|
|
@export
|
|
macro TestNewlineInString() {
|
|
Print('Hello, World!\n');
|
|
}
|
|
|
|
const kConstexprConst: constexpr int31 = 5;
|
|
const kIntptrConst: intptr = 4;
|
|
const kSmiConst: Smi = 3;
|
|
|
|
@export
|
|
macro TestModuleConstBindings() {
|
|
check(kConstexprConst == Int32Constant(5));
|
|
check(kIntptrConst == 4);
|
|
check(kSmiConst == 3);
|
|
}
|
|
|
|
@export
|
|
macro TestLocalConstBindings() {
|
|
const x: constexpr int31 = 3;
|
|
const xSmi: Smi = x;
|
|
{
|
|
const x: Smi = x + FromConstexpr<Smi>(1);
|
|
check(x == xSmi + 1);
|
|
const xSmi: Smi = x;
|
|
check(x == xSmi);
|
|
check(x == 4);
|
|
}
|
|
check(xSmi == 3);
|
|
check(x == xSmi);
|
|
}
|
|
|
|
struct TestStructA {
|
|
indexes: FixedArray;
|
|
i: Smi;
|
|
k: Number;
|
|
}
|
|
|
|
struct TestStructB {
|
|
x: TestStructA;
|
|
y: Smi;
|
|
}
|
|
|
|
@export
|
|
macro TestStruct1(i: TestStructA): Smi {
|
|
return i.i;
|
|
}
|
|
|
|
@export
|
|
macro TestStruct2(implicit context: Context)(): TestStructA {
|
|
return TestStructA{
|
|
indexes: UnsafeCast<FixedArray>(kEmptyFixedArray),
|
|
i: 27,
|
|
k: 31
|
|
};
|
|
}
|
|
|
|
@export
|
|
macro TestStruct3(implicit context: Context)(): TestStructA {
|
|
let a: TestStructA =
|
|
TestStructA{indexes: UnsafeCast<FixedArray>(kEmptyFixedArray), i: 13, k: 5};
|
|
let _b: TestStructA = a;
|
|
let c: TestStructA = TestStruct2();
|
|
a.i = TestStruct1(c);
|
|
a.k = a.i;
|
|
let d: TestStructB;
|
|
d.x = a;
|
|
d = TestStructB{x: a, y: 7};
|
|
let _e: TestStructA = d.x;
|
|
let f: Smi = TestStructA{
|
|
indexes: UnsafeCast<FixedArray>(kEmptyFixedArray),
|
|
i: 27,
|
|
k: 31
|
|
}.i;
|
|
f = TestStruct2().i;
|
|
return a;
|
|
}
|
|
|
|
struct TestStructC {
|
|
x: TestStructA;
|
|
y: TestStructA;
|
|
}
|
|
|
|
@export
|
|
macro TestStruct4(implicit context: Context)(): TestStructC {
|
|
return TestStructC{x: TestStruct2(), y: TestStruct2()};
|
|
}
|
|
|
|
macro TestStructInLabel(implicit context: Context)(): never labels
|
|
Foo(TestStructA) {
|
|
goto Foo(TestStruct2());
|
|
}
|
|
macro CallTestStructInLabel(implicit context: Context)() {
|
|
try {
|
|
TestStructInLabel() otherwise Foo;
|
|
}
|
|
label Foo(_s: TestStructA) {}
|
|
}
|
|
|
|
// This macro tests different versions of the for-loop where some parts
|
|
// are (not) present.
|
|
@export
|
|
macro TestForLoop() {
|
|
let sum: Smi = 0;
|
|
for (let i: Smi = 0; i < 5; ++i) sum += i;
|
|
check(sum == 10);
|
|
|
|
sum = 0;
|
|
let j: Smi = 0;
|
|
for (; j < 5; ++j) sum += j;
|
|
check(sum == 10);
|
|
|
|
sum = 0;
|
|
j = 0;
|
|
for (; j < 5;) sum += j++;
|
|
check(sum == 10);
|
|
|
|
// Check that break works. No test expression.
|
|
sum = 0;
|
|
for (let i: Smi = 0;; ++i) {
|
|
if (i == 5) break;
|
|
sum += i;
|
|
}
|
|
check(sum == 10);
|
|
|
|
sum = 0;
|
|
j = 0;
|
|
for (;;) {
|
|
if (j == 5) break;
|
|
sum += j;
|
|
j++;
|
|
}
|
|
check(sum == 10);
|
|
|
|
// The following tests are the same as above, but use continue to skip
|
|
// index 3.
|
|
sum = 0;
|
|
for (let i: Smi = 0; i < 5; ++i) {
|
|
if (i == 3) continue;
|
|
sum += i;
|
|
}
|
|
check(sum == 7);
|
|
|
|
sum = 0;
|
|
j = 0;
|
|
for (; j < 5; ++j) {
|
|
if (j == 3) continue;
|
|
sum += j;
|
|
}
|
|
check(sum == 7);
|
|
|
|
sum = 0;
|
|
j = 0;
|
|
for (; j < 5;) {
|
|
if (j == 3) {
|
|
j++;
|
|
continue;
|
|
}
|
|
sum += j;
|
|
j++;
|
|
}
|
|
check(sum == 7);
|
|
|
|
sum = 0;
|
|
for (let i: Smi = 0;; ++i) {
|
|
if (i == 3) continue;
|
|
if (i == 5) break;
|
|
sum += i;
|
|
}
|
|
check(sum == 7);
|
|
|
|
sum = 0;
|
|
j = 0;
|
|
for (;;) {
|
|
if (j == 3) {
|
|
j++;
|
|
continue;
|
|
}
|
|
|
|
if (j == 5) break;
|
|
sum += j;
|
|
j++;
|
|
}
|
|
check(sum == 7);
|
|
|
|
j = 0;
|
|
try {
|
|
for (;;) {
|
|
if (++j == 10) goto Exit;
|
|
}
|
|
}
|
|
label Exit {
|
|
check(j == 10);
|
|
}
|
|
|
|
// Test if we can handle uninitialized values on the stack.
|
|
let _i: Smi;
|
|
for (let j: Smi = 0; j < 10; ++j) {
|
|
}
|
|
}
|
|
|
|
@export
|
|
macro TestSubtyping(x: Smi) {
|
|
const _foo: Object = x;
|
|
}
|
|
|
|
macro IncrementIfSmi<A: type>(x: A): A {
|
|
typeswitch (x) {
|
|
case (x: Smi): {
|
|
return x + 1;
|
|
}
|
|
case (o: A): {
|
|
return o;
|
|
}
|
|
}
|
|
}
|
|
|
|
type NumberOrFixedArray = Number | FixedArray;
|
|
macro TypeswitchExample(implicit context: Context)(x: NumberOrFixedArray):
|
|
int32 {
|
|
let result: int32 = 0;
|
|
typeswitch (IncrementIfSmi(x)) {
|
|
case (_x: FixedArray): {
|
|
result = result + 1;
|
|
}
|
|
case (Number): {
|
|
result = result + 2;
|
|
}
|
|
}
|
|
|
|
result = result * 10;
|
|
|
|
typeswitch (IncrementIfSmi(x)) {
|
|
case (x: Smi): {
|
|
result = result + Convert<int32>(x);
|
|
}
|
|
case (a: FixedArray): {
|
|
result = result + Convert<int32>(a.length);
|
|
}
|
|
case (_x: HeapNumber): {
|
|
result = result + 7;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
@export
|
|
macro TestTypeswitch(implicit context: Context)() {
|
|
check(TypeswitchExample(FromConstexpr<Smi>(5)) == 26);
|
|
const a: FixedArray = AllocateZeroedFixedArray(3);
|
|
check(TypeswitchExample(a) == 13);
|
|
check(TypeswitchExample(FromConstexpr<Number>(0.5)) == 27);
|
|
}
|
|
|
|
@export
|
|
macro TestTypeswitchAsanLsanFailure(implicit context: Context)(obj: Object) {
|
|
typeswitch (obj) {
|
|
case (_o: Smi): {
|
|
}
|
|
case (_o: JSTypedArray): {
|
|
}
|
|
case (_o: JSReceiver): {
|
|
}
|
|
case (_o: HeapObject): {
|
|
}
|
|
}
|
|
}
|
|
|
|
macro ExampleGenericOverload<A: type>(o: Object): A {
|
|
return o;
|
|
}
|
|
macro ExampleGenericOverload<A: type>(o: Smi): A {
|
|
return o + 1;
|
|
}
|
|
|
|
@export
|
|
macro TestGenericOverload(implicit context: Context)() {
|
|
const xSmi: Smi = 5;
|
|
const xObject: Object = xSmi;
|
|
check(ExampleGenericOverload<Smi>(xSmi) == 6);
|
|
check(UnsafeCast<Smi>(ExampleGenericOverload<Object>(xObject)) == 5);
|
|
}
|
|
|
|
@export
|
|
macro TestEquality(implicit context: Context)() {
|
|
const notEqual: bool =
|
|
AllocateHeapNumberWithValue(0.5) != AllocateHeapNumberWithValue(0.5);
|
|
check(!notEqual);
|
|
const equal: bool =
|
|
AllocateHeapNumberWithValue(0.5) == AllocateHeapNumberWithValue(0.5);
|
|
check(equal);
|
|
}
|
|
|
|
macro BoolToBranch(x: bool): never
|
|
labels Taken, NotTaken {
|
|
if (x) {
|
|
goto Taken;
|
|
} else {
|
|
goto NotTaken;
|
|
}
|
|
}
|
|
|
|
@export
|
|
macro TestOrAnd1(x: bool, y: bool, z: bool): bool {
|
|
return BoolToBranch(x) || y && z ? true : false;
|
|
}
|
|
|
|
@export
|
|
macro TestOrAnd2(x: bool, y: bool, z: bool): bool {
|
|
return x || BoolToBranch(y) && z ? true : false;
|
|
}
|
|
|
|
@export
|
|
macro TestOrAnd3(x: bool, y: bool, z: bool): bool {
|
|
return x || y && BoolToBranch(z) ? true : false;
|
|
}
|
|
|
|
@export
|
|
macro TestAndOr1(x: bool, y: bool, z: bool): bool {
|
|
return BoolToBranch(x) && y || z ? true : false;
|
|
}
|
|
|
|
@export
|
|
macro TestAndOr2(x: bool, y: bool, z: bool): bool {
|
|
return x && BoolToBranch(y) || z ? true : false;
|
|
}
|
|
|
|
@export
|
|
macro TestAndOr3(x: bool, y: bool, z: bool): bool {
|
|
return x && y || BoolToBranch(z) ? true : false;
|
|
}
|
|
|
|
@export
|
|
macro TestLogicalOperators() {
|
|
check(TestAndOr1(true, true, true));
|
|
check(TestAndOr2(true, true, true));
|
|
check(TestAndOr3(true, true, true));
|
|
check(TestAndOr1(true, true, false));
|
|
check(TestAndOr2(true, true, false));
|
|
check(TestAndOr3(true, true, false));
|
|
check(TestAndOr1(true, false, true));
|
|
check(TestAndOr2(true, false, true));
|
|
check(TestAndOr3(true, false, true));
|
|
check(!TestAndOr1(true, false, false));
|
|
check(!TestAndOr2(true, false, false));
|
|
check(!TestAndOr3(true, false, false));
|
|
check(TestAndOr1(false, true, true));
|
|
check(TestAndOr2(false, true, true));
|
|
check(TestAndOr3(false, true, true));
|
|
check(!TestAndOr1(false, true, false));
|
|
check(!TestAndOr2(false, true, false));
|
|
check(!TestAndOr3(false, true, false));
|
|
check(TestAndOr1(false, false, true));
|
|
check(TestAndOr2(false, false, true));
|
|
check(TestAndOr3(false, false, true));
|
|
check(!TestAndOr1(false, false, false));
|
|
check(!TestAndOr2(false, false, false));
|
|
check(!TestAndOr3(false, false, false));
|
|
check(TestOrAnd1(true, true, true));
|
|
check(TestOrAnd2(true, true, true));
|
|
check(TestOrAnd3(true, true, true));
|
|
check(TestOrAnd1(true, true, false));
|
|
check(TestOrAnd2(true, true, false));
|
|
check(TestOrAnd3(true, true, false));
|
|
check(TestOrAnd1(true, false, true));
|
|
check(TestOrAnd2(true, false, true));
|
|
check(TestOrAnd3(true, false, true));
|
|
check(TestOrAnd1(true, false, false));
|
|
check(TestOrAnd2(true, false, false));
|
|
check(TestOrAnd3(true, false, false));
|
|
check(TestOrAnd1(false, true, true));
|
|
check(TestOrAnd2(false, true, true));
|
|
check(TestOrAnd3(false, true, true));
|
|
check(!TestOrAnd1(false, true, false));
|
|
check(!TestOrAnd2(false, true, false));
|
|
check(!TestOrAnd3(false, true, false));
|
|
check(!TestOrAnd1(false, false, true));
|
|
check(!TestOrAnd2(false, false, true));
|
|
check(!TestOrAnd3(false, false, true));
|
|
check(!TestOrAnd1(false, false, false));
|
|
check(!TestOrAnd2(false, false, false));
|
|
check(!TestOrAnd3(false, false, false));
|
|
}
|
|
|
|
@export
|
|
macro TestCall(i: Smi): Smi labels A {
|
|
if (i < 5) return i;
|
|
goto A;
|
|
}
|
|
|
|
@export
|
|
macro TestOtherwiseWithCode1() {
|
|
let v: Smi = 0;
|
|
let s: Smi = 1;
|
|
try {
|
|
TestCall(10) otherwise goto B(++s);
|
|
}
|
|
label B(v1: Smi) {
|
|
v = v1;
|
|
}
|
|
assert(v == 2);
|
|
}
|
|
|
|
@export
|
|
macro TestOtherwiseWithCode2() {
|
|
let s: Smi = 0;
|
|
for (let i: Smi = 0; i < 10; ++i) {
|
|
TestCall(i) otherwise break;
|
|
++s;
|
|
}
|
|
assert(s == 5);
|
|
}
|
|
|
|
@export
|
|
macro TestOtherwiseWithCode3() {
|
|
let s: Smi = 0;
|
|
for (let i: Smi = 0; i < 10; ++i) {
|
|
s += TestCall(i) otherwise break;
|
|
}
|
|
assert(s == 10);
|
|
}
|
|
|
|
@export
|
|
macro TestForwardLabel() {
|
|
try {
|
|
goto A;
|
|
}
|
|
label A {
|
|
goto B(5);
|
|
}
|
|
label B(b: Smi) {
|
|
assert(b == 5);
|
|
}
|
|
}
|
|
|
|
@export
|
|
macro TestQualifiedAccess(implicit context: Context)() {
|
|
let s: Smi = 0;
|
|
check(!array::IsJSArray(s));
|
|
}
|
|
|
|
@export
|
|
macro TestCatch1(implicit context: Context)(): Smi {
|
|
let r: Smi = 0;
|
|
try {
|
|
ThrowTypeError(kInvalidArrayLength);
|
|
} catch (_e) {
|
|
r = 1;
|
|
return r;
|
|
}
|
|
}
|
|
|
|
@export
|
|
macro TestCatch2Wrapper(implicit context: Context)(): never {
|
|
ThrowTypeError(kInvalidArrayLength);
|
|
}
|
|
|
|
@export
|
|
macro TestCatch2(implicit context: Context)(): Smi {
|
|
let r: Smi = 0;
|
|
try {
|
|
TestCatch2Wrapper();
|
|
} catch (_e) {
|
|
r = 2;
|
|
return r;
|
|
}
|
|
}
|
|
|
|
@export
|
|
macro TestCatch3WrapperWithLabel(implicit context: Context)():
|
|
never labels _Abort {
|
|
ThrowTypeError(kInvalidArrayLength);
|
|
}
|
|
|
|
@export
|
|
macro TestCatch3(implicit context: Context)(): Smi {
|
|
let r: Smi = 0;
|
|
try {
|
|
TestCatch3WrapperWithLabel() otherwise Abort;
|
|
}
|
|
label Abort {
|
|
return -1;
|
|
}
|
|
catch (_e) {
|
|
r = 2;
|
|
return r;
|
|
}
|
|
}
|
|
|
|
// This test doesn't actually test the functionality of iterators,
|
|
// it's only purpose is to make sure tha the CSA macros in the
|
|
// IteratorBuiltinsAssembler match the signatures provided in
|
|
// iterator.tq.
|
|
@export
|
|
macro TestIterator(implicit context: Context)(o: Object, map: Map) {
|
|
try {
|
|
const t1: Object = iterator::GetIteratorMethod(o);
|
|
const t2: iterator::IteratorRecord = iterator::GetIterator(o);
|
|
|
|
const _t3: Object = iterator::IteratorStep(t2) otherwise Fail;
|
|
const t4: Object = iterator::IteratorStep(t2, map) otherwise Fail;
|
|
|
|
const t5: Object = iterator::IteratorValue(t4);
|
|
const _t6: Object = iterator::IteratorValue(t4, map);
|
|
|
|
const _t7: JSArray = iterator::IterableToList(t1, t1);
|
|
|
|
iterator::IteratorCloseOnException(t2, t5);
|
|
}
|
|
label Fail {}
|
|
}
|
|
|
|
@export
|
|
macro TestFrame1(implicit context: Context)() {
|
|
const f: Frame = LoadFramePointer();
|
|
const frameType: FrameType =
|
|
Cast<FrameType>(f.context_or_frame_type) otherwise unreachable;
|
|
assert(frameType == STUB_FRAME);
|
|
assert(f.caller == LoadParentFramePointer());
|
|
typeswitch (f) {
|
|
case (_f: StandardFrame): {
|
|
unreachable;
|
|
}
|
|
case (_f: ArgumentsAdaptorFrame): {
|
|
unreachable;
|
|
}
|
|
case (_f: StubFrame): {
|
|
}
|
|
}
|
|
}
|
|
|
|
@export
|
|
macro TestNew(implicit context: Context)() {
|
|
const f: JSArray = NewJSArray();
|
|
assert(f.IsEmpty());
|
|
f.length = 0;
|
|
}
|
|
|
|
struct TestInner {
|
|
SetX(newValue: int32) {
|
|
this.x = newValue;
|
|
}
|
|
GetX(): int32 {
|
|
return this.x;
|
|
}
|
|
x: int32;
|
|
y: int32;
|
|
}
|
|
|
|
struct TestOuter {
|
|
a: int32;
|
|
b: TestInner;
|
|
c: int32;
|
|
}
|
|
|
|
@export
|
|
macro TestStructConstructor(implicit context: Context)() {
|
|
// Test default constructor
|
|
let a: TestOuter = TestOuter{a: 5, b: TestInner{x: 6, y: 7}, c: 8};
|
|
assert(a.a == 5);
|
|
assert(a.b.x == 6);
|
|
assert(a.b.y == 7);
|
|
assert(a.c == 8);
|
|
a.b.x = 1;
|
|
assert(a.b.x == 1);
|
|
a.b.SetX(2);
|
|
assert(a.b.x == 2);
|
|
assert(a.b.GetX() == 2);
|
|
}
|
|
|
|
class InternalClass {
|
|
Flip() labels NotASmi {
|
|
const tmp = Cast<Smi>(this.b) otherwise NotASmi;
|
|
this.b = this.a;
|
|
this.a = tmp;
|
|
}
|
|
a: Smi;
|
|
b: Number;
|
|
}
|
|
|
|
macro NewInternalClass(x: Smi): InternalClass {
|
|
return new InternalClass{a: x, b: x + 1};
|
|
}
|
|
|
|
@export
|
|
macro TestInternalClass(implicit context: Context)() {
|
|
const o = NewInternalClass(5);
|
|
o.Flip() otherwise unreachable;
|
|
check(o.a == 6);
|
|
check(o.b == 5);
|
|
}
|
|
|
|
struct StructWithConst {
|
|
TestMethod1(): int32 {
|
|
return this.b;
|
|
}
|
|
TestMethod2(): Object {
|
|
return this.a;
|
|
}
|
|
a: Object;
|
|
const b: int32;
|
|
}
|
|
|
|
@export
|
|
macro TestConstInStructs() {
|
|
const x = StructWithConst{a: Null, b: 1};
|
|
let y = StructWithConst{a: Null, b: 1};
|
|
y.a = Undefined;
|
|
const _copy = x;
|
|
}
|
|
|
|
struct TestIterator {
|
|
Next(): Object labels NoMore {
|
|
if (this.count-- == 0) goto NoMore;
|
|
return Hole;
|
|
}
|
|
count: Smi;
|
|
}
|
|
|
|
@export
|
|
macro TestNewFixedArrayFromSpread(implicit context: Context)(): Object {
|
|
const i = TestIterator{count: 5};
|
|
return new FixedArray{map: kFixedArrayMap, length: 5, objects: ...i};
|
|
}
|
|
|
|
class SmiPair {
|
|
GetA():&Smi {
|
|
return & this.a;
|
|
}
|
|
a: Smi;
|
|
b: Smi;
|
|
}
|
|
|
|
macro Swap<T: type>(a:&T, b:&T) {
|
|
const tmp = * a;
|
|
* a = * b;
|
|
* b = tmp;
|
|
}
|
|
|
|
@export
|
|
macro TestReferences() {
|
|
const array = new SmiPair{a: 7, b: 2};
|
|
const ref:&Smi = & array.a;
|
|
* ref = 3 + * ref;
|
|
-- * ref;
|
|
Swap(& array.b, array.GetA());
|
|
check(array.a == 2);
|
|
check(array.b == 9);
|
|
}
|
|
|
|
@export
|
|
macro TestStaticAssert() {
|
|
StaticAssert(1 + 2 == 3);
|
|
}
|
|
|
|
class SmiBox {
|
|
value: Smi;
|
|
unrelated: Smi;
|
|
}
|
|
|
|
builtin NewSmiBox(implicit c: Context)(value: Smi): SmiBox {
|
|
return new SmiBox{value, unrelated: 0};
|
|
}
|
|
|
|
@export
|
|
macro TestLoadEliminationNoWrite(implicit c: Context)() {
|
|
const box = NewSmiBox(123);
|
|
const v1 = box.value;
|
|
const v2 = (box.unrelated == 0) ? box.value : box.value;
|
|
StaticAssert(WordEqual(v1, v2));
|
|
}
|
|
|
|
}
|