github.com/cloudwego/frugal@v0.1.15/internal/atm/emu/emu_test.go (about)

     1  /*
     2   * Copyright 2022 ByteDance Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package emu
    18  
    19  import (
    20      `testing`
    21      `unsafe`
    22  
    23      `github.com/cloudwego/frugal/internal/atm/hir`
    24      `github.com/davecgh/go-spew/spew`
    25  )
    26  
    27  var (
    28      testfn = hir.RegisterGCall(testemu_pfunc, func(ctx hir.CallContext) {
    29          var v0 struct {P unsafe.Pointer; L uint64}
    30          var v1 struct {P unsafe.Pointer; L uint64}
    31          var v2 struct {P unsafe.Pointer; L uint64}
    32          if !ctx.Verify("*i*i*i", "*i*i") {
    33              panic("invalid testemu_pfunc call")
    34          }
    35          v0.P = ctx.Ap(0)
    36          v0.L = ctx.Au(1)
    37          v1.P = ctx.Ap(2)
    38          v1.L = ctx.Au(3)
    39          v2.P = ctx.Ap(4)
    40          v2.L = ctx.Au(5)
    41          r0, r1 := testemu_pfunc(
    42              *(*string)(unsafe.Pointer(&v0)),
    43              *(*string)(unsafe.Pointer(&v1)),
    44              *(*string)(unsafe.Pointer(&v2)),
    45          )
    46          ctx.Ru(1, uint64(len(r0)))
    47          ctx.Ru(3, uint64(len(r1)))
    48          ctx.Rp(0, *(*unsafe.Pointer)(unsafe.Pointer(&r0)))
    49          ctx.Rp(2, *(*unsafe.Pointer)(unsafe.Pointer(&r1)))
    50      })
    51  )
    52  
    53  func testemu_pfunc(a string, b string, c string) (d string, e string) {
    54      d = a + b
    55      e = b + c
    56      return
    57  }
    58  
    59  func runEmulator(init func(emu *Emulator), prog func(p *hir.Builder)) *Emulator {
    60      pb := hir.CreateBuilder()
    61      prog(pb)
    62      emu := LoadProgram(pb.Build())
    63      if init != nil {
    64          init(emu)
    65      }
    66      emu.Run()
    67      return emu
    68  }
    69  
    70  func TestEmu_OpCode_GCALL(t *testing.T) {
    71      a := "aaa"
    72      b := "bbb"
    73      c := "ccc"
    74      emu := runEmulator(nil, func(p *hir.Builder) {
    75          p.IP(&a, hir.P0)
    76          p.IP(&b, hir.P1)
    77          p.IP(&c, hir.P2)
    78          p.LQ(hir.P0, 8, hir.R0)
    79          p.LP(hir.P0, 0, hir.P0)
    80          p.LQ(hir.P1, 8, hir.R1)
    81          p.LP(hir.P1, 0, hir.P1)
    82          p.LQ(hir.P2, 8, hir.R2)
    83          p.LP(hir.P2, 0, hir.P2)
    84          p.GCALL(testfn).A0(hir.P0).A1(hir.R0).A2(hir.P1).A3(hir.R1).A4(hir.P2).A5(hir.R2).R0(hir.P0).R1(hir.R0).R2(hir.P1).R3(hir.R1)
    85          p.RET().R0(hir.P0).R1(hir.R0).R2(hir.P1).R3(hir.R1)
    86      })
    87      val := [2]struct{P unsafe.Pointer; L uint64} {
    88          {P: emu.Rp(0), L: emu.Ru(1)},
    89          {P: emu.Rp(2), L: emu.Ru(3)},
    90      }
    91      spew.Dump(*(*[2]string)(unsafe.Pointer(&val)))
    92  }