gitee.com/quant1x/num@v0.3.2/asm/c2goasm/epilogue_test.go (about)

     1  /*
     2   * Minio Cloud Storage, (C) 2017 Minio, 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 main
    18  
    19  import (
    20  	"strings"
    21  	"testing"
    22  )
    23  
    24  func equalString(a, b []string) bool {
    25  
    26  	if len(a) != len(b) {
    27  		return false
    28  	}
    29  
    30  	for i := range a {
    31  		if a[i] != b[i] {
    32  			return false
    33  		}
    34  	}
    35  	return true
    36  }
    37  
    38  func testEpilogue(t *testing.T, prologue, epilogue string, expected Epilogue) {
    39  	src := strings.Split(epilogue, "\n")
    40  	stack := extractEpilogueInfo(src, 0, len(src))
    41  
    42  	for _, line := range strings.Split(prologue, "\n") {
    43  		isPrologue := stack.isPrologueInstruction(line)
    44  		if !isPrologue {
    45  			t.Errorf("testEpilogue(): \nexpected true\ngot      %#v", isPrologue)
    46  		}
    47  	}
    48  
    49  	if stack.StackSize != expected.StackSize || stack.AlignedStack != expected.AlignedStack ||
    50  		stack.VZeroUpper != expected.VZeroUpper || !equalString(stack.Pops, expected.Pops) ||
    51  		stack.SetRbpInstr != expected.SetRbpInstr {
    52  		t.Errorf("testEpilogue(): \nexpected %#v\ngot      %#v", expected, stack)
    53  	}
    54  }
    55  
    56  func TestEpilogues(t *testing.T) {
    57  
    58  	asmPrologue1 := `	   push    rbp
    59  	   mov     rbp, rsp`
    60  
    61  	epilogue1 := Epilogue{SetRbpInstr: true, VZeroUpper: true}
    62  	epilogue1.Pops = append(epilogue1.Pops, "rbp")
    63  
    64  	asmEpilogue1 := `	    pop     rbp
    65  	    vzeroupper
    66  	    ret`
    67  
    68  	testEpilogue(t, asmPrologue1, asmEpilogue1, epilogue1)
    69  
    70  	/***********************************************************************************/
    71  
    72  	asmPrologue2 := `	   push    rbp
    73  	   mov     rbp, rsp
    74  	   push    r15
    75  	   push    r14
    76  	   push    r13
    77  	   push    r12
    78  	   push    rbx
    79  	   and     rsp, -32
    80  	   sub     rsp, 864`
    81  
    82  	epilogue2 := Epilogue{SetRbpInstr: true, StackSize: 864, AlignedStack: true, AlignValue: 32}
    83  	epilogue2.Pops = append(epilogue2.Pops, "rbp", "r15", "r14", "r13", "r12", "rbx")
    84  
    85  	asmEpilogue2 := `        lea     rsp, [rbp - 40]
    86          pop     rbx
    87          pop     r12
    88          pop     r13
    89          pop     r14
    90          pop     r15
    91          pop     rbp`
    92  
    93  	testEpilogue(t, asmPrologue2, asmEpilogue2, epilogue2)
    94  
    95  	/***********************************************************************************/
    96  
    97  	asmPrologue3 := `push    rbp
    98  	   mov     rbp, rsp
    99  	   push    r15
   100  	   push    r14
   101  	   push    r13
   102  	   push    r12
   103  	   push    rbx`
   104  
   105  	epilogue3 := Epilogue{SetRbpInstr: true}
   106  	epilogue3.Pops = append(epilogue3.Pops, "rbp", "r15", "r14", "r13", "r12", "rbx")
   107  
   108  	asmEpilogue3 := `        pop     rbx
   109          pop     r12
   110          pop     r13
   111          pop     r14
   112          pop     r15
   113          pop     rbp`
   114  
   115  	testEpilogue(t, asmPrologue3, asmEpilogue3, epilogue3)
   116  
   117  	/***********************************************************************************/
   118  
   119  	asmPrologue4 := `push    rbp
   120  	   mov     rbp, rsp
   121  	   push    r15
   122  	   push    r14
   123  	   push    r13
   124  	   push    r12
   125  	   push    rbx
   126  	   sub     rsp, 152`
   127  
   128  	epilogue4 := Epilogue{SetRbpInstr: true, StackSize: 152}
   129  	epilogue4.Pops = append(epilogue4.Pops, "rbp", "r15", "r14", "r13", "r12", "rbx")
   130  
   131  	asmEpilogue4 := `        add     rsp, 152
   132          pop     rbx
   133          pop     r12
   134          pop     r13
   135          pop     r14
   136          pop     r15
   137          pop     rbp`
   138  
   139  	testEpilogue(t, asmPrologue4, asmEpilogue4, epilogue4)
   140  
   141  	/***********************************************************************************/
   142  
   143  	asmPrologue5 := `push    rbp
   144  	   mov     rbp, rsp
   145  	   push    r15
   146  	   push    r14
   147  	   push    r13
   148  	   push    r12
   149  	   push    rbx
   150  	   and     rsp, -32
   151  	   sub     rsp, 192`
   152  
   153  	epilogue5 := Epilogue{SetRbpInstr: true, StackSize: 192, AlignedStack: true, AlignValue: 32, VZeroUpper: true}
   154  	epilogue5.Pops = append(epilogue5.Pops, "rbp", "r15", "r14", "r13", "r12", "rbx")
   155  
   156  	asmEpilogue5 := `        lea     rsp, [rbp - 40]
   157          pop     rbx
   158          pop     r12
   159          pop     r13
   160          pop     r14
   161          pop     r15
   162          pop     rbp
   163          vzeroupper
   164          ret`
   165  
   166  	testEpilogue(t, asmPrologue5, asmEpilogue5, epilogue5)
   167  
   168  	/***********************************************************************************/
   169  
   170  	asmPrologue6 := `push	rbp
   171  	mov	rbp, rsp
   172  	push	r15
   173  	push	r14
   174  	push	r13
   175  	push	r12
   176  	push	rbx
   177  	push	rax`
   178  
   179  	epilogue6 := Epilogue{SetRbpInstr: true, VZeroUpper: true}
   180  	epilogue6.Pops = append(epilogue6.Pops, "rbp", "r15", "r14", "r13", "r12", "rbx")
   181  
   182  	// `add rsp, 8` counters the additional `push rax` (there are 7 pushes and 6 pops)
   183  	asmEpilogue6 := `	add	rsp, 8
   184  	pop	rbx
   185  	pop	r12
   186  	pop	r13
   187  	pop	r14
   188  	pop	r15
   189  	pop	rbp
   190  	vzeroupper
   191  	ret`
   192  
   193  	testEpilogue(t, asmPrologue6, asmEpilogue6, epilogue6)
   194  
   195  	asmPrologue7 := `        push    rbp
   196          mov     rbp, rsp
   197          push    r15
   198          push    r14
   199          push    r13
   200          push    r12
   201          push    rbx
   202          and     rsp, -8
   203          push    rax`
   204  
   205  	asmEpilogue7 := `        lea     rsp, [rbp - 40]
   206          pop     rbx
   207          pop     r12
   208          pop     r13
   209          pop     r14
   210          pop     r15
   211          pop     rbp
   212          ret`
   213  
   214  	epilogue7 := Epilogue{SetRbpInstr: true, VZeroUpper: false, StackSize: 8}
   215  	epilogue7.Pops = append(epilogue7.Pops, "rbp", "r15", "r14", "r13", "r12", "rbx")
   216  
   217  	testEpilogue(t, asmPrologue7, asmEpilogue7, epilogue7)
   218  
   219  	asmPrologue8 := `push    rbp
   220          mov     rbp, rsp
   221          and     rsp, -8`
   222  
   223  	asmEpilogue8 := `mov     rsp, rbp
   224          pop     rbp
   225          ret`
   226  
   227  	epilogue8 := Epilogue{SetRbpInstr: true, VZeroUpper: false, StackSize: 0}
   228  	epilogue8.Pops = append(epilogue8.Pops, "rbp")
   229  
   230  	testEpilogue(t, asmPrologue8, asmEpilogue8, epilogue8)
   231  
   232  }