# Copyright (c) 2021-2022 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

definitions:
  - name: pandasm_header
    template: |
      .language PandaAssembly

      .record panda.Object <external>

      .record R {
        u1             fu1       <static>
        u8             fu8       <static>
        i8             fi8       <static>
        u16            fu16      <static>
        i16            fi16      <static>
        u32            fu32      <static>
        i32            fi32      <static>
        u64            fu64      <static>
        i64            fi64      <static>
        f32            ff32      <static>
        f64            ff64      <static>
        # objects:
        i32[]          fi32Array <static>
        panda.Object   fObj      <static>
        panda.Object[] fObjArray <static>
      }

  - name: PandaAssembly_header
    template: |
      .language PandaAssembly

      .record panda.Object <external>

      .record R {
        u1             fu1       <static>
        i8             fi8       <static>
        u16            fu16      <static>
        i16            fi16      <static>
        i32            fi32      <static>
        i64            fi64      <static>
        f32            ff32      <static>
        f64            ff64      <static>
        # objects:
        i32[]          fi32Array <static>
        panda.Object   fObj      <static>
        panda.Object[] fObjArray <static>
      }

tests:
  - file-name: "ldstatic.64"
    isa:
      title: Get static field
      description: >
        Get static field value by field_id and put it into accumulator.
      instructions:
        - sig: ldstatic.64 field_id
          acc: out:b64
          format: [op_id_16]
    commands:

      - file-name: "with_non_static_field_id"
        description: Check that verifier reports an error when the field doesn't resolve to a static valid field
        isa:
          verification:
            - field_id_static
        header-template: []
        check-type: exit-positive
        code-template: |
          .record W {
            u1    fu1
            i8    fi8
            u16   fu16
            i16   fi16
            i32   fi32
            i64   fi64
            f32   ff32
            f64   ff64
            W     fW
            i32[] fi32Array
            W[]   fWArray
          }
          .function void W.object_function(W a0) {
            return.void
          }
          .function void static_function() {
            return.void
          }

          .function i32 main() {
              ldstatic.64 %s
        cases:
          - values:
            - W.fu1
            tags: [verifier]
            runner-options: ['verifier-failure', 'verifier-config']
            bugid: ['1324', '1828']
          - values:
            - W.fi8
            tags: [verifier]
            runner-options: ['verifier-failure', 'verifier-config']
            bugid: ['1324', '1828']
          - values:
            - W.fu16
            tags: [verifier]
            runner-options: ['verifier-failure', 'verifier-config']
            bugid: ['1324', '1828']
          - values:
            - W.fi16
            tags: [verifier]
            runner-options: ['verifier-failure', 'verifier-config']
            bugid: ['1324', '1828']
          - values:
            - W.fi32
            tags: [verifier]
            runner-options: ['verifier-failure', 'verifier-config']
            bugid: ['1324', '1828']
          - values:
            - W.fi64
            tags: [verifier]
            runner-options: ['verifier-failure', 'verifier-config']
            bugid: ['1324', '1828']
          - values:
            - W.ff32
            tags: [verifier]
            runner-options: ['verifier-failure', 'verifier-config']
            bugid: ['1324', '1828']
          - values:
            - W.ff64
            tags: [verifier]
            runner-options: ['verifier-failure', 'verifier-config']
            bugid: ['1324', '1828']
          - values:
            - W.fW
            tags: [verifier]
            runner-options: ['verifier-failure', 'verifier-config']
            bugid: ['1324', '1828']
          - values:
            - W.fi32Array
            tags: [verifier]
            runner-options: ['verifier-failure', 'verifier-config']
            bugid: ['1324', '1828']
          - values:
            - W.fWArray
            tags: [verifier]
            runner-options: ['verifier-failure', 'verifier-config']
            bugid: ['1324', '1828']
          - values:
            - W
            runner-options: [compile-failure]
          - values:
            - W.object_function
            runner-options: [compile-failure]
          - values:
            - static_function
            runner-options: [compile-failure]
          - values:
            - unknown_function
            runner-options: [compile-failure]
          - values:
            - 0
            runner-options: [compile-failure]
          - values:
            - -1.1
            runner-options: [compile-failure]
          - values:
            - "null"
            runner-options: [compile-failure]
          - values:
            - "\"abc\""
            runner-options: [compile-failure]


      - file-name: "with_wrong_field_size_p"
        description: Check that verifier reports an error when the field resolves to a field with size that is not corresponding to bytecode in PandaAssembly context.
        isa:
          verification:
            - field_id_size
        header-template: [pandasm_header]
        check-type: exit-positive
        tags: [verifier]
        runner-options: ['verifier-failure', 'verifier-config']
        bugid: ['1834', '2088']
        code-template: |

          .function i32 main() {
            ldstatic.64 %s
        cases:
          - values:
            - R.fu1
          - values:
            - R.fu8
          - values:
            - R.fi8
          - values:
            - R.fu16
          - values:
            - R.fi16
          - values:
            - R.fu32
          - values:
            - R.fi32
          - values:
            - R.ff32
            bugid: ['6094']
          - values:
            - R.fObj
          - values:
            - R.fObjArray
          - values:
            - R.fi32Array


      - file-name: "with_wrong_field_size_j"
        description: Check that verifier reports an error when the field resolves to a field with size that is not corresponding to bytecode in PandaAssembly context.
        isa:
          verification:
            - field_id_size
        header-template: [PandaAssembly_header]
        check-type: exit-positive
        tags: [verifier, pa-verifier]
        runner-options: [verifier-failure, use-pa, verifier-config]
        bugid: ["5271"]
        code-template: |

          .function i32 main() {
            ldstatic.64 %s
        cases:
          - values:
            - R.fu1
          - values:
            - R.fi8
          - values:
            - R.fu16
          - values:
            - R.fi16
          - values:
            - R.fi32
          - values:
            - R.ff32
            bugid: ['6094']
          - values:
            - R.fObj
          - values:
            - R.fObjArray
          - values:
            - R.fi32Array


      - file-name: "from_all_int_field_types_p"
        description: Check that accumulator value is loaded from field into accumulator in PandaAssembly context. More tests on ldstatic.64 can be found in ststatic.64 tests.
        isa:
          description: Get static field value by field_id and put it into accumulator.
        header-template: [pandasm_header]
        check-type: exit-positive
        tags: ['tsan']
        code-template: |

          .function i32 main() {
            ldai.64 %s
            ststatic.64 R.f%s
            movi.64 v15, %s
            ldstatic.64 R.f%s
            %s v15
            jeqz success
            ldai 1
            return
          success:
        cases:
          # u64
          - values: [0, 'u64', 0, 'u64', 'ucmp.64']
          - values: [0xffffffffffffffff, 'u64', 0xffffffffffffffff, 'u64', 'ucmp.64']
          - values: [0xa5a5a5a5a5a5a5a5, 'u64', 0xa5a5a5a5a5a5a5a5, 'u64', 'ucmp.64']
          # i64
          - values: [0, 'i64', 0, 'i64', 'cmp.64']
          - values: [-1, 'i64', -1, 'i64', 'cmp.64']
          - values: [-6510615555426900571, 'i64', -6510615555426900571, 'i64', 'cmp.64']


      - file-name: "from_all_int_field_types_j"
        description: Check that accumulator value is loaded from field into accumulator in PandaAssembly context. More tests on ldstatic.64 can be found in ststatic.64 tests.
        isa:
          description: Get static field value by field_id and put it into accumulator.
        header-template: [PandaAssembly_header]
        runner-options: [use-pa]
        check-type: exit-positive
        tags: ['tsan']
        code-template: |

          .function i32 main() {
            ldai.64 %s
            ststatic.64 R.f%s
            movi.64 v15, %s
            ldstatic.64 R.f%s
            %s v15
            jeqz success
            ldai 1
            return
          success:
        cases:
          # i64
          - values: [0, 'i64', 0, 'i64', 'cmp.64']
          - values: [-1, 'i64', -1, 'i64', 'cmp.64']
          - values: [-6510615555426900571, 'i64', -6510615555426900571, 'i64', 'cmp.64']


      - file-name: "from_float_field_type_p"
        description: Check that accumulator value is loaded from field into accumulator in PandaAssembly context. More tests on ldstatic.64 can be found in ststatic.64 tests.
        isa:
          instructions:
            - sig: ldstatic.64 field_id
              acc: out:b64
              format: [op_id_16]
        tags: ['irtoc_ignore']
        header-template: [pandasm_header]
        check-type: exit-positive
        code-template: |

          .function i32 main() {
            fldai.64 %s
            ststatic.64 R.ff64
            lda.null
            fmovi.64 v15, %s
            ldstatic.64 R.ff64
            fcmpg.64 v15
            %s
            jeqz success
            ldai 1
            return
          success:
        cases:
          # f64
          - values: ['0.0', '0.0', '']
          - values: ['-6510615555426900571.0', '-6510615555426900571.0', '']
          - values: ['0x7FFFFFFFFFFFFFFF', '0x7FFFFFFFFFFFFFFF', 'subi 1']    # NaN
          - values: ['0x7ff0000000000000', '0x7ff0000000000000', '']    # + Inf
          - values: ['0xfff0000000000000', '0xfff0000000000000', '']    # - Inf

      - file-name: "from_float_field_type_j"
        description: Check that accumulator value is loaded from field into accumulator in PandaAssembly context. More tests on ldstatic.64 can be found in ststatic.64 tests.
        isa:
          instructions:
            - sig: ldstatic.64 field_id
              acc: out:b64
              format: [op_id_16]
        header-template: [PandaAssembly_header]
        tags: ['irtoc_ignore']
        runner-options: [use-pa]
        check-type: exit-positive
        code-template: |

          .function i32 main() {
            fldai.64 %s
            ststatic.64 R.ff64
            lda.null
            fmovi.64 v15, %s
            ldstatic.64 R.ff64
            fcmpg.64 v15
            %s
            jeqz success
            ldai 1
            return
          success:
        cases:
          # f64
          - values: ['0.0', '0.0', '']
          - values: ['-6510615555426900571.0', '-6510615555426900571.0', '']
          - values: ['0x7FFFFFFFFFFFFFFF', '0x7FFFFFFFFFFFFFFF', 'subi 1']    # NaN
          - values: ['0x7ff0000000000000', '0x7ff0000000000000', '']    # + Inf
          - values: ['0xfff0000000000000', '0xfff0000000000000', '']    # - Inf

      - file-name: "x_init_p"
        description: Check that ExceptionInInitializerError is thrown if an unexpected exception occurs in static initializer.
        isa:
          exceptions:
            - x_init
        header-template: []
        check-type: empty
        tags: ['tsan', 'irtoc_ignore']
        bugid: ['5330']
        code-template: |

          .language PandaAssembly

          .record panda.ExceptionInInitializerError <external>
          .record panda.NullPointerException <external>
          .record E1 {}
          .record R {
              f64     ff64    <static>
          }

          .function void R.func() <cctor> {
              %s
              return.void
          }

          .function i32 main() {
          begin:
              ldstatic.64 R.ff64
              ldai 2
              return
          end:
          catch:
              ldai 0
              return
          catch_all:
              ldai 1
              return
          .catch panda.ExceptionInInitializerError, begin, end, catch
          .catchall begin, end, catch_all
          }
        cases:
          - values:
            - |
              #
                  newobj v0, E1
                  throw v0
          - values:
            - |
              #
                  newobj v0, panda.NullPointerException
                  throw v0
          - values:
            - |
              #
                  movi v1, 0
                  ldai 1
                  div2 v1     # divide by zero
          - values:
            - |
              #
                  movi v1, 10
                  newarr v1, v1, i32[]
                  ldai 10
                  ldarr v1    # get ArrayIndexOutOfBoundsException

      - file-name: "x_init_j"
        description: Check that ExceptionInInitializerError is thrown if an unexpected exception occurs in static initializer.
        isa:
          exceptions:
            - x_init
        header-template: []
        check-type: empty
        tags: ['tsan', 'irtoc_ignore']
        runner-options: ['use-pa']
        code-template: |

          .language PandaAssembly

          .record panda.ExceptionInInitializerError <external>
          .record panda.NullPointerException <external>
          .record E1 {}
          .record R {
              f64     ff64    <static>
          }
          .record Q <panda.extends=R> {
              f64     ff64    <static>
          }
          .function void R.func() <cctor> {
              %s
              return.void
          }

          .function i32 main() {
          begin:
              ldstatic.64 Q.ff64
              ldai 2
              return
          end:
          catch:
              ldai 0
              return
          catch_all:
              ldai 1
              return
          .catch panda.ExceptionInInitializerError, begin, end, catch
          .catchall begin, end, catch_all
          }
        cases:
          - values:
            - |
              #
                  newobj v0, E1
                  throw v0
          - values:
            - |
              #
                  newobj v0, panda.NullPointerException
                  throw v0
          - values:
            - |
              #
                  movi v1, 0
                  ldai 1
                  div2 v1     # divide by zero
          - values:
            - |
              #
                  movi v1, 10
                  newarr v1, v1, i32[]
                  ldai 10
                  ldarr v1    # get ArrayIndexOutOfBoundsException