1/*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16declare interface ArkTools {
17    isAOTCompiled(args: any): boolean;
18}
19declare function print(arg:any):string;
20function replace(a : number)
21{
22    return a;
23}
24
25function doclz32(x: any): number {
26    return Math.clz32(x);
27}
28
29function printclz32(x: any) {
30    try {
31        print(doclz32(x));
32    } finally {
33    }
34}
35
36// Check without params
37//aot: [trace] aot inline builtin: Math.clz32, caller function name:func_main_0@builtinMathClz32
38print(Math.clz32()); //: 32
39
40// Check with single int param
41//aot: [trace] aot inline builtin: Math.clz32, caller function name:func_main_0@builtinMathClz32
42print(Math.clz32(0)); //: 32
43//aot: [trace] aot inline builtin: Math.clz32, caller function name:func_main_0@builtinMathClz32
44print(Math.clz32(1)); //: 31
45//aot: [trace] aot inline builtin: Math.clz32, caller function name:func_main_0@builtinMathClz32
46print(Math.clz32(1 << 31)) //: 0
47//aot: [trace] aot inline builtin: Math.clz32, caller function name:func_main_0@builtinMathClz32
48print(Math.clz32(1 << 30)) //: 1
49//aot: [trace] aot inline builtin: Math.clz32, caller function name:func_main_0@builtinMathClz32
50print(Math.clz32(-5)); //: 0
51
52// 0b11
53//aot: [trace] aot inline builtin: Math.clz32, caller function name:func_main_0@builtinMathClz32
54print(Math.clz32(3)); //: 30
55
56// MAX_UINT32 + 3
57//aot: [trace] aot inline builtin: Math.clz32, caller function name:func_main_0@builtinMathClz32
58print(Math.clz32(4294967298)); //: 30
59
60// Check with single float param
61//aot: [trace] aot inline builtin: Math.clz32, caller function name:func_main_0@builtinMathClz32
62print(Math.clz32(1.9999999999999)); //: 31
63//aot: [trace] aot inline builtin: Math.clz32, caller function name:func_main_0@builtinMathClz32
64print(Math.clz32(126.55555555555)); //: 25
65//aot: [trace] aot inline builtin: Math.clz32, caller function name:func_main_0@builtinMathClz32
66print(Math.clz32(126.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999)) //: 25
67
68// Negative arguments
69// -1073741824 (0xC0000000) ->
70//aot: [trace] aot inline builtin: Math.clz32, caller function name:func_main_0@builtinMathClz32
71print(Math.clz32((1 << 30) + (1 << 31))) //: 0
72//aot: [trace] aot inline builtin: Math.clz32, caller function name:func_main_0@builtinMathClz32
73print(Math.clz32(-5)) //: 0
74//aot: [trace] aot inline builtin: Math.clz32, caller function name:func_main_0@builtinMathClz32
75print(Math.clz32(-126.99999999999999999999999)) //: 0
76
77
78// Corner cases
79//aot: [trace] aot inline builtin: Math.clz32, caller function name:func_main_0@builtinMathClz32
80print(Math.clz32(NaN)) //: 32
81//aot: [trace] aot inline builtin: Math.clz32, caller function name:func_main_0@builtinMathClz32
82print(Math.clz32(+0.0)) //: 32
83//aot: [trace] aot inline builtin: Math.clz32, caller function name:func_main_0@builtinMathClz32
84print(Math.clz32(-0.0)) //: 32
85//aot: [trace] aot inline builtin: Math.clz32, caller function name:func_main_0@builtinMathClz32
86print(Math.clz32(Infinity)); //: 32
87//aot: [trace] aot inline builtin: Math.clz32, caller function name:func_main_0@builtinMathClz32
88print(Math.clz32(-Infinity)); //: 32
89
90//aot: [trace] aot inline builtin: Math.clz32, caller function name:#*#doclz32@builtinMathClz32
91printclz32(4); //: 29
92//aot: [trace] aot inline builtin: Math.clz32, caller function name:#*#doclz32@builtinMathClz32
93//aot: [trace] Check Type: NotNumber1
94printclz32("abc"); //: 32
95//aot: [trace] aot inline builtin: Math.clz32, caller function name:#*#doclz32@builtinMathClz32
96//aot: [trace] Check Type: NotNumber1
97printclz32("abcd"); //: 32
98
99let true_clz32 = Math.clz32
100if (ArkTools.isAOTCompiled(printclz32)) {
101    // Replace standard builtin after call to standard builtin was profiled
102    Math.clz32 = replace
103}
104printclz32(-8); //pgo: 0
105//aot: [trace] Check Type: NotCallTarget1
106//aot: -8
107
108printclz32("abc"); //pgo: 32
109//aot: [trace] Check Type: NotCallTarget1
110//aot: abc
111
112Math.clz32 = true_clz32
113
114// Check IR correctness inside try-block
115try {
116    //aot: [trace] aot inline builtin: Math.clz32, caller function name:#*#doclz32@builtinMathClz32
117    printclz32(16); //: 27
118    //aot: [trace] aot inline builtin: Math.clz32, caller function name:#*#doclz32@builtinMathClz32
119    //aot: [trace] Check Type: NotNumber1
120    printclz32("abc"); //: 32
121} catch (e) {
122}
123
124let obj = {};
125obj.valueOf = (() => { return 32; })
126//aot: [trace] aot inline builtin: Math.clz32, caller function name:func_main_0@builtinMathClz32
127//aot: [trace] Check Type: NotNumber1
128print(Math.clz32(obj)); //: 26
129
130function Throwing() {
131    this.value = 64;
132}
133Throwing.prototype.valueOf = function() {
134    if (this.value > 100) {
135        throw new Error("so big");
136    }
137    return this.value;
138}
139let throwingObj = new Throwing();
140
141try {
142    print(Math.clz32(throwingObj)); //: 25
143    throwingObj.value = 128;
144    print(Math.clz32(throwingObj)); //: Error: so big
145} catch(e) {
146    print(e);
147} finally {
148    print(Math.clz32(obj)); //: 26
149}