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;
20
21function printZero(x: any) {
22    if (Object.is(x, -0)) {
23        print("-0");
24    } else {
25        print(x);
26    }
27}
28function replace(a : number)
29{
30    return a;
31}
32
33// Use try to prevent inlining to main
34function printMin(x: any, y: any) {
35    try {
36        print(Math.min(x, y));
37    } finally {
38    }
39}
40
41function printMin1(x: any) {
42    try {
43        print(Math.min(x));
44    } finally {
45    }
46}
47
48
49let doubleObj = {
50    valueOf: () => { return 2.7; }
51}
52
53let nanObj = {
54    valueOf: () => { return "something"; }
55}
56
57let obj = {
58    valueOf: () => {
59        print("obj.valueOf")
60        return -23;
61    }
62};
63
64// Check without params
65//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
66print(Math.min()); //: Infinity
67
68// Check with single param
69//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
70print(Math.min(0)); //: 0
71//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
72print(Math.min(567)); //: 567
73//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
74print(Math.min(-1e80)); //: -1e+80
75
76// Check with special float params
77//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
78print(Math.min(Infinity)); //: Infinity
79//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
80print(Math.min(-Infinity)); //: -Infinity
81//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
82print(Math.min(NaN)); //: NaN
83
84// Check with 2 int params
85//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
86print(Math.min(3, 300)); //: 3
87//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
88print(Math.min(300, 3)); //: 3
89//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
90print(Math.min(3, -2)); //: -2
91//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
92print(Math.min(-22, -2)); //: -22
93//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
94print(Math.min(-1, -1)); //: -1
95
96// // Check with 2 float params
97//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
98print(Math.min(3.2, 300.7)); //: 3.2
99//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
100print(Math.min(300.7, 3.2)); //: 3.2
101//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
102print(Math.min(3e11, -2e10)); //: -20000000000
103//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
104print(Math.min(-22.1, -2e-10)); //: -22.1
105//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
106print(Math.min(-1.8, -1.8)); //: -1.8
107//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
108print(Math.min(Infinity, -1.8)); //: -1.8
109//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
110print(Math.min(-1.8, Infinity)); //: -1.8
111//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
112print(Math.min(-Infinity, -1.8)); //: -Infinity
113//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
114print(Math.min(-1.8, -Infinity)); //: -Infinity
115//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
116print(Math.min(-1.8, NaN)); //: NaN
117//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
118print(Math.min(NaN, -1.8)); //: NaN
119//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
120print(Math.min(-Infinity, NaN)); //: NaN
121//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
122print(Math.min(Infinity, NaN)); //: NaN
123
124
125// Check 0 and -0
126//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
127//aot: [trace] aot inline function name: #*#printZero@builtinMathMin caller function name: func_main_0@builtinMathMin
128//aot: [trace] aot inline builtin: Object.is, caller function name:#*#printZero@builtinMathMin
129printZero(Math.min(0, -0));  //: -0
130//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
131//aot: [trace] aot inline function name: #*#printZero@builtinMathMin caller function name: func_main_0@builtinMathMin
132//aot: [trace] aot inline builtin: Object.is, caller function name:#*#printZero@builtinMathMin
133printZero(Math.min(-0, 0));  //: -0
134//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
135//aot: [trace] aot inline function name: #*#printZero@builtinMathMin caller function name: func_main_0@builtinMathMin
136//aot: [trace] aot inline builtin: Object.is, caller function name:#*#printZero@builtinMathMin
137printZero(Math.min(0, 0));   //: 0
138//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
139//aot: [trace] aot inline function name: #*#printZero@builtinMathMin caller function name: func_main_0@builtinMathMin
140//aot: [trace] aot inline builtin: Object.is, caller function name:#*#printZero@builtinMathMin
141printZero(Math.min(-0, -0)); //: -0
142//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
143//aot: [trace] aot inline function name: #*#printZero@builtinMathMin caller function name: func_main_0@builtinMathMin
144//aot: [trace] aot inline builtin: Object.is, caller function name:#*#printZero@builtinMathMin
145printZero(Math.min(5, -0)); //: -0
146//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
147//aot: [trace] aot inline function name: #*#printZero@builtinMathMin caller function name: func_main_0@builtinMathMin
148//aot: [trace] aot inline builtin: Object.is, caller function name:#*#printZero@builtinMathMin
149printZero(Math.min(5, 0)); //: 0
150
151// Check with int and float param
152//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
153print(Math.min(1.5, 3)); //: 1.5
154//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
155print(Math.min(3, 1.5)); //: 1.5
156//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
157print(Math.min(2.5, 1)); //: 1
158//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
159print(Math.min(1, 2.5)); //: 1
160//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
161print(Math.min(1, Infinity)); //: 1
162//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
163print(Math.min(5, NaN)); //: NaN
164//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
165print(Math.min(NaN, 5)); //: NaN
166
167// Check with 3 params
168//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
169print(Math.min(2, 4, 6)); //: 2
170//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
171print(Math.min(4, 6, 2)); //: 2
172//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
173print(Math.min(6, 2, 4)); //: 2
174//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
175print(Math.min(-1, 1, -2.5)); //: -2.5
176
177// Check with 4 params
178//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
179print(Math.min(4, 0, -2, Infinity)); //: -2
180
181// Check with 5 params
182//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
183print(Math.min(-1, -2, -1.5, -2, -8)); //: -8
184
185// Replace standard builtin
186let trueMin = Math.min
187Math.min = replace
188print(Math.min(-1.001, -90)); //: -1.001
189Math.min = trueMin
190
191//aot: [trace] aot inline builtin: Math.min, caller function name:#*#printMin@builtinMathMin
192printMin(-12, 1); //: -12
193// Call standard builtin with non-number param
194//aot: [trace] aot inline builtin: Math.min, caller function name:#*#printMin@builtinMathMin
195//aot: [trace] Check Type: NotNumber2
196printMin("abc", 1); //: NaN
197//aot: [trace] aot inline builtin: Math.min, caller function name:#*#printMin@builtinMathMin
198//aot: [trace] Check Type: NotNumber2
199printMin("-12", 1); //: -12
200
201if (ArkTools.isAOTCompiled(printMin)) {
202    // Replace standard builtin after call to standard builtin was profiled
203    Math.min = replace
204}
205//aot: [trace] Check Type: NotCallTarget1
206printMin(5, -12); //pgo: -12
207                  //aot: 5
208//aot: [trace] Check Type: NotCallTarget1
209printMin("abc", 2); //pgo: NaN
210                    //aot: abc
211Math.min = trueMin
212
213// Check IR correctness inside try-block
214try {
215    //aot: [trace] aot inline builtin: Math.min, caller function name:#*#printMin@builtinMathMin
216    printMin(19, 12); //: 12
217    //aot: [trace] aot inline builtin: Math.min, caller function name:#*#printMin@builtinMathMin
218    //aot: [trace] Check Type: NotNumber2
219    printMin("abc", 5); //: NaN
220} catch (e) {
221}
222
223//aot: [trace] aot inline builtin: Math.min, caller function name:#*#printMin1@builtinMathMin
224//aot: [trace] Check Type: InconsistentType1
225//: obj.valueOf
226printMin1(obj); //: -23
227//aot: [trace] aot inline builtin: Math.min, caller function name:#*#printMin1@builtinMathMin
228//aot: [trace] Check Type: InconsistentType1
229printMin1(doubleObj); //: 2.7
230//aot: [trace] aot inline builtin: Math.min, caller function name:#*#printMin@builtinMathMin
231//aot: [trace] Check Type: NotNumber2
232printMin(doubleObj, doubleObj); //: 2.7
233//aot: [trace] aot inline builtin: Math.min, caller function name:#*#printMin@builtinMathMin
234//aot: [trace] Check Type: NotNumber2
235//: obj.valueOf
236printMin(nanObj, obj); //: NaN
237//aot: [trace] aot inline builtin: Math.min, caller function name:#*#printMin@builtinMathMin
238//aot: [trace] Check Type: NotNumber2
239//: obj.valueOf
240printMin(24, obj); //: -23
241
242// call obj.valueOf twice
243//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
244//aot: [trace] Check Type: NotNumber2
245//: obj.valueOf
246//: obj.valueOf
247print(Math.min(NaN, obj, obj)); //: NaN
248