81186ff41d
Variables/return values with constexpr type cannot have multiple assignments. We check this now. For conditionals, it is important to always infer a non-constexpr type. This CL adds the ability to map any type (including union types) to be mapped to their non-constexpr variant. Conditionals infer their type as the non-constexpr version of a combination of the two branch types. In addition, this improves subtyping for constexpr types: If A extends B, then constexpr A extends constexpr B. This makes it necessary to clean up "constexpr String", which has nothing to do with tagged values. Bug: v8:7793 Change-Id: Ia4d3cd5dc98f45b0ec89adf05c5c6111a0e51cc6 Reviewed-on: https://chromium-review.googlesource.com/1122864 Commit-Queue: Tobias Tebbi <tebbi@chromium.org> Reviewed-by: Daniel Clifford <danno@chromium.org> Cr-Commit-Position: refs/heads/master@{#54167}
232 lines
6.1 KiB
Plaintext
232 lines
6.1 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.
|
|
|
|
module 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(String, Smi) {
|
|
goto Label3('foo', 7);
|
|
}
|
|
|
|
macro TestConstexpr1() {
|
|
check(from_constexpr<bool>(IsFastElementsKind(PACKED_SMI_ELEMENTS)));
|
|
}
|
|
|
|
macro TestConstexprIf() {
|
|
check(ElementsKindTestHelper1(UINT8_ELEMENTS));
|
|
check(ElementsKindTestHelper1(UINT16_ELEMENTS));
|
|
check(!ElementsKindTestHelper1(UINT32_ELEMENTS));
|
|
}
|
|
|
|
macro TestConstexprReturn() {
|
|
check(from_constexpr<bool>(ElementsKindTestHelper3(UINT8_ELEMENTS)));
|
|
check(from_constexpr<bool>(ElementsKindTestHelper3(UINT16_ELEMENTS)));
|
|
check(!from_constexpr<bool>(ElementsKindTestHelper3(UINT32_ELEMENTS)));
|
|
check(from_constexpr<bool>(!ElementsKindTestHelper3(UINT32_ELEMENTS)));
|
|
}
|
|
|
|
macro TestGotoLabel(): Boolean {
|
|
try {
|
|
LabelTestHelper1() otherwise Label1;
|
|
}
|
|
label Label1 {
|
|
return True;
|
|
}
|
|
}
|
|
|
|
macro TestGotoLabelWithOneParameter(): Boolean {
|
|
try {
|
|
LabelTestHelper2() otherwise Label2;
|
|
}
|
|
label Label2(smi: Smi) {
|
|
check(smi == 42);
|
|
return True;
|
|
}
|
|
}
|
|
|
|
macro TestGotoLabelWithTwoParameters(): Boolean {
|
|
try {
|
|
LabelTestHelper3() otherwise Label3;
|
|
}
|
|
label Label3(str: String, smi: Smi) {
|
|
check(str == 'foo');
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
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 param2;
|
|
}
|
|
|
|
macro TestMacroSpecialization() {
|
|
try {
|
|
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);
|
|
check(GenericMacroTestWithLabels<Object>(Null) otherwise Fail == Null);
|
|
check(GenericMacroTestWithLabels<Object>(False) otherwise Fail == False);
|
|
}
|
|
label Fail {
|
|
unreachable;
|
|
}
|
|
}
|
|
|
|
builtin TestHelperPlus1(context : Context, x : Smi) : Smi {
|
|
return x + 1;
|
|
}
|
|
builtin TestHelperPlus2(context : Context, x : Smi) : Smi {
|
|
return x + 2;
|
|
}
|
|
|
|
macro TestFunctionPointers(context : Context) : Boolean {
|
|
let fptr : builtin(Context, Smi) => Smi = TestHelperPlus1;
|
|
check(fptr(context, 42) == 43);
|
|
fptr = TestHelperPlus2;
|
|
check(fptr(context, 42) == 44);
|
|
return True;
|
|
}
|
|
|
|
macro TestVariableRedeclaration(context : Context) : Boolean {
|
|
let var1 : int31 = from_constexpr<bool>(42 == 0) ? 0 : 1;
|
|
let var2 : int31 = from_constexpr<bool>(42 == 0) ? 1 : 0;
|
|
return True;
|
|
}
|
|
|
|
macro TestTernaryOperator(x : Smi) : Smi {
|
|
let b : bool = x < 0 ? true : false;
|
|
return b ? x - 10 : x + 100;
|
|
}
|
|
|
|
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 SmiToSmi = builtin(Smi) => Smi;
|
|
macro TestTypeAlias(x : SmiToSmi) : Code {
|
|
return x;
|
|
}
|
|
|
|
macro TestUnsafeCast(c: Context, n: Number): Boolean {
|
|
if (TaggedIsSmi(n)) {
|
|
let m: Smi = unsafe_cast<Smi>(n);
|
|
|
|
check(TestHelperPlus1(c, m) == 11);
|
|
return True;
|
|
}
|
|
return False;
|
|
}
|
|
|
|
macro TestHexLiteral() {
|
|
check(convert<intptr>(0xffff) + 1 == 0x10000);
|
|
check(convert<intptr>(-0xffff) == -65535);
|
|
}
|
|
|
|
macro TestLargeIntegerLiterals(c: Context) {
|
|
let x: int32 = 0x40000000;
|
|
let y: int32 = 0x7fffffff;
|
|
}
|
|
|
|
macro TestMultilineAssert() {
|
|
let someVeryLongVariableNameThatWillCauseLineBreaks: Smi = 5;
|
|
check(someVeryLongVariableNameThatWillCauseLineBreaks > 0
|
|
&& someVeryLongVariableNameThatWillCauseLineBreaks < 10);
|
|
}
|
|
|
|
macro TestNewlineInString() {
|
|
Print('Hello, World!\n');
|
|
}
|
|
}
|