1# Copyright (c) 2021 Huawei Device Co., Ltd. 2# Licensed under the Apache License, Version 2.0 (the "License"); 3# you may not use this file except in compliance with the License. 4# You may obtain a copy of the License at 5# 6# http://www.apache.org/licenses/LICENSE-2.0 7# 8# Unless required by applicable law or agreed to in writing, software 9# distributed under the License is distributed on an "AS IS" BASIS, 10# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11# See the License for the specific language governing permissions and 12# limitations under the License. 13 14definitions: 15 - name: java_header 16 template: | 17 .language Java 18 .record java.lang.NullPointerException <external> 19 .record java.lang.RuntimeException <external> 20 .record java.lang.Exception <external> 21 .record java.lang.Throwable <external> 22 .record java.lang.Object <external> 23 .record E1 <java.extends=java.lang.Throwable> {} 24 25 - name: pandasm_header 26 template: | 27 .language PandaAssembly 28 .record panda.NullPointerException <external> 29 .record panda.Object <external> 30 .record E1 {} 31 .record E2 {} 32 .record E3 {} 33 34tests: 35 - file-name: "throw" 36 isa: 37 title: Throw exception 38 description: Throw an exception located in register. 39 instructions: 40 - sig: throw v:in:ref 41 acc: none 42 format: [op_v_8] 43 commands: 44 45 - file-name: "when_reg_is_invalid" 46 description: Check that compilation fails if register is invalid 47 isa: 48 instructions: 49 - sig: throw v:in:ref 50 acc: none 51 format: [op_v_8] 52 verification: 53 - v1_throw_type 54 runner-options: ['compile-failure'] 55 header-template: [] 56 check-type: empty 57 code-template: | 58 59 .function i32 main() { 60 throw %s 61 } 62 cases: 63 - values: ['v256'] 64 - values: ['v65535'] 65 - values: ['a0'] 66 - values: [''] 67 - values: ['main'] 68 - values: ['i32'] 69 - values: ['throw'] 70 - values: ['v0, v0'] 71 - values: ['}'] 72 - values: ['v255'] 73 runner-options: ['compile-only'] 74 75 - file-name: "when_reg_v_is_uninitialized" 76 description: Check that verifier report error when the register is not initialized 77 isa: 78 instructions: 79 - sig: throw v:in:ref 80 acc: none 81 format: [op_v_8] 82 verification: 83 - v1_throw_type 84 runner-options: ['verifier-failure', 'verifier-debug-config'] 85 tags: ['verifier'] 86 header-template: [] 87 check-type: empty 88 code-template: | 89 90 .function i32 main() { 91 throw %s 92 } 93 cases: 94 - values: ['v0'] 95 - values: ['v255'] 96 97 98 - file-name: "when_reg_a_is_uninitialized" 99 description: Check that compiler reports error when 'a' register is not initialized 100 isa: 101 instructions: 102 - sig: throw v:in:ref 103 acc: none 104 format: [op_v_8] 105 verification: 106 - v1_throw_type 107 runner-options: ['compile-failure'] 108 header-template: [] 109 check-type: empty 110 code-template: | 111 .record E {} 112 113 .function void func(E a0) <static> { 114 throw %s 115 return.void 116 } 117 118 .function i32 main() { 119 newobj v0, E 120 call.short func, v0 121 } 122 cases: 123 - values: ['a0'] 124 runner-options: ['run-failure'] 125 - values: ['a1'] 126 - values: ['a255'] 127 128 129 - file-name: "when_reg_is_null_pa" 130 description: Check that NullPointerException is thrown when register value is null 131 isa: 132 exceptions: [x_null] 133 header-template: ['pandasm_header'] 134 check-type: empty 135 code-template: | 136 137 .function i32 main() { 138 jmp try_begin 139 catch_NPE_block_begin: 140 ldai 0 141 return 142 try_begin: 143 mov.null v0 144 throw v0 145 try_end: 146 .catch panda.NullPointerException, try_begin, try_end, catch_NPE_block_begin 147 } 148 149 150 - file-name: "with_wrong_reg_value_pa" 151 description: "Check that VM thread fails when register contains not a Throwable" 152 isa: 153 description: Throw an exception located in register. 154 verification: 155 - v1_throw_type 156 header-template: ['pandasm_header'] 157 check-type: empty 158 runner-options: ['verifier-failure', 'verifier-debug-config'] 159 tags: ['verifier'] 160 code-template: | 161 162 .function i32 main() { 163 jmp try_begin 164 catch_all_block_begin: 165 ldai 0 166 return 167 try_begin: 168 %s 169 throw v0 170 try_end: 171 .catchall try_begin, try_end, catch_all_block_begin 172 } 173 cases: 174 - values: 175 - movi v0, 100 176 - values: 177 - movi.64 v0, 0x1234567890 178 - values: 179 - fmovi.64 v0, 3.1415926 180 - values: 181 - newobj v0, panda.Object 182 bugid: ['1688'] 183 ignore: true 184 - values: 185 - newobj v0, E1 186 bugid: ['1688'] 187 ignore: true 188 - values: 189 - | 190 # 191 lda.type panda.Object 192 sta.obj v0 193 bugid: ['1688'] 194 ignore: true 195 - values: 196 - | 197 # 198 lda.str "abc" 199 sta.obj v0 200 bugid: ['1688'] 201 ignore: true 202 203 204 - file-name: "with_multiple_catch_blocks_pa" 205 description: "Check that correct catch block is selected" 206 isa: 207 description: Throw an exception located in register. The current method is searched for the first exception handler that matches the class of exception. 208 header-template: ['pandasm_header'] 209 check-type: none 210 code-template: | 211 212 .function i32 main() { 213 jmp try_begin 214 catch_NPE_block_begin: 215 ldai %s 216 return 217 catch_E1_block_begin: 218 ldai %s 219 return 220 catch_E2_block_begin: 221 ldai %s 222 return 223 catch_E3_block_begin: 224 ldai %s 225 return 226 try_begin: 227 newobj v0, %s 228 throw v0 229 try_end: 230 .catch panda.NullPointerException, try_begin, try_end, catch_NPE_block_begin 231 .catch E1, try_begin, try_end, catch_E1_block_begin 232 .catch E2, try_begin, try_end, catch_E2_block_begin 233 .catch E3, try_begin, try_end, catch_E3_block_begin 234 cases: 235 - values: [0, 2, 3, 4, panda.NullPointerException] 236 - values: [1, 0, 3, 4, E1] 237 - values: [1, 2, 0, 4, E2] 238 - values: [1, 2, 3, 0, E3] 239 240 241 - file-name: "with_catchall_pa" 242 description: "Check that catchall block is selected correctly" 243 isa: 244 description: Throw an exception located in register. The current method is searched for the first exception handler that matches the class of exception. 245 header-template: ['pandasm_header'] 246 check-type: empty 247 code-template: | 248 249 .function i32 main() { 250 jmp try_begin 251 catch_all_block_begin: 252 ldai %s 253 return 254 catch_E1_block_begin: 255 ldai %s 256 return 257 catch_E2_block_begin: 258 ldai %s 259 return 260 try_begin: 261 newobj v0, %s 262 throw v0 263 try_end: 264 .catch E1, try_begin, try_end, catch_E1_block_begin 265 .catchall try_begin, try_end, catch_all_block_begin 266 .catch E2, try_begin, try_end, catch_E2_block_begin 267 } 268 cases: 269 - values: [1, 0, 3, E1] 270 - values: [0, 2, 3, E2] 271 - values: [0, 2, 3, panda.NullPointerException] 272 273 274 - file-name: "with_reg_value_check_pa" 275 description: "Check that register keeps ref to exception object in catch block" 276 isa: 277 description: Throw an exception located in register. 278 header-template: ['pandasm_header'] 279 check-type: empty 280 bugid: ["3975"] 281 code-template: | 282 283 .function i32 main() { 284 jmp try_begin 285 catch_block_begin: 286 lda.obj v0 287 jne.obj v1, return_ne_num 288 ldai 0 289 return 290 return_ne_num: 291 ldai 1 292 return 293 try_begin: 294 newobj v0, %s 295 mov.obj v1, v0 296 throw v0 297 try_end: 298 .catch E1, try_begin, try_end, catch_block_begin 299 .catch E2, try_begin, try_end, catch_block_begin 300 .catchall try_begin, try_end, catch_block_begin 301 } 302 cases: 303 - values: 304 - E1 305 - values: 306 - E2 307 - values: 308 - panda.NullPointerException 309 310 311 - file-name: "with_propagation_to_outer_block_pa" 312 description: "Check exception propagation to outer try-catch block" 313 isa: 314 description: The current method is searched for the first exception handler that matches the class of exception. If exception handler is found, control is passed to the exception handler. 315 header-template: ['pandasm_header'] 316 check-type: empty 317 tags: ['tsan'] 318 code-template: | 319 320 .function i32 main() { 321 begin3: 322 newobj v0, %s 323 lda.obj v0 324 begin2: 325 mov.obj v1, v0 326 begin1: 327 throw v0 328 end1: 329 end2: 330 end3: 331 ldai 4 332 return 333 catch1: 334 %s 335 return 336 catch2: 337 %s 338 return 339 catch3: 340 %s 341 return 342 .catch E1, begin1, end1, catch1 343 .catch E2, begin2, end2, catch2 344 .catch E3, begin3, end3, catch3 345 } 346 cases: 347 - values: 348 - E1 349 - | 350 # 351 jne.obj v1, return_ne_num 352 ldai 0 353 return 354 return_ne_num: 355 ldai 1 356 - ldai 2 357 - ldai 3 358 - values: 359 - E2 360 - ldai 2 361 - | 362 # 363 jne.obj v1, return_ne_num 364 ldai 0 365 return 366 return_ne_num: 367 ldai 1 368 - ldai 3 369 bugid: ['3975'] 370 - values: 371 - E3 372 - ldai 2 373 - ldai 3 374 - | 375 # 376 jne.obj v1, return_ne_num 377 ldai 0 378 return 379 return_ne_num: 380 ldai 1 381 bugid: ['3975'] 382 383 384 - file-name: "with_propagation_to_outer_frame_pa" 385 description: "Check exception propagation to outer frame" 386 isa: 387 description: If no exception handler is found, the frame of invoker is restored. If such frame exists, the exception is re-thrown. 388 header-template: ['pandasm_header'] 389 check-type: empty 390 bugid: ["1837"] 391 code-template: | 392 393 .function i32 f2() { 394 newobj v0, %s 395 try2_begin: 396 throw v0 397 try2_end: 398 ldai 0 399 return 400 .catch %s, try2_begin, try2_end, try2_end 401 } 402 403 .function i32 f1() { 404 try1_begin: 405 call f2 406 return 407 try1_end: 408 ldai 0 409 return 410 .catch %s, try1_begin, try1_end, try1_end 411 } 412 413 .function i32 main() { 414 try_begin: 415 call f1 416 ldai %s 417 return 418 try_end: 419 catch_block_begin: 420 ldai %s 421 return 422 .catch %s, try_begin, try_end, catch_block_begin 423 } 424 cases: 425 - values: [E2, E1, E2, 0, 1, E3] 426 - values: [E3, E1, E2, 1, 0, E3] 427 428 429 - file-name: "with_no_handler_pa" 430 description: "Check exception propagation to outer frame and VM thread exit if handler is not found." 431 isa: 432 description: > 433 If no exception handler is found, the frame of invoker is restored. If such frame exists, the exception is re-thrown. If no 434 exception handler is found, the frame of invoker is restored. If such frame exists, the exception is re-thrown. 435 If no such frame exists, the current VM thread exits. 436 header-template: ['pandasm_header'] 437 check-type: empty 438 runner-options: ['run-failure'] 439 code-template: | 440 441 .function i32 f2() { 442 newobj v0, %s 443 try2_begin: 444 throw v0 445 try2_end: 446 return 447 .catch %s, try2_begin, try2_end, try2_end 448 } 449 450 .function i32 f1() { 451 try1_begin: 452 call f2 453 try1_end: 454 return 455 .catch %s, try1_begin, try1_end, try1_end 456 } 457 458 .function i32 main() { 459 try_begin: 460 call f1 461 try_end: 462 ldai %s 463 return 464 catch_block_begin: 465 ldai %s 466 return 467 .catch %s, try_begin, try_end, catch_block_begin 468 } 469 cases: 470 - values: [E2, E1, E3, 0, 0, E1] 471 - values: [E3, E1, E1, 0, 0, E1] 472 473 474