gitee.com/quant1x/num@v0.3.2/asm/c2goasm/arguments.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  	"errors"
    21  	"fmt"
    22  	"regexp"
    23  	"strconv"
    24  	"strings"
    25  )
    26  
    27  type StackArgs struct {
    28  	Number        int
    29  	OffsetToFirst int
    30  }
    31  
    32  func argumentsOnStack(lines []string) StackArgs {
    33  
    34  	offsets := make(map[uint]bool)
    35  
    36  	for _, l := range lines {
    37  		l, _ = stripComments(l)
    38  		if match := regexpRbpLoadHigher.FindStringSubmatch(l); len(match) > 1 {
    39  			offset, _ := strconv.Atoi(match[1])
    40  			if _, found := offsets[uint(offset)]; !found {
    41  				offsets[uint(offset)] = true
    42  			}
    43  		}
    44  	}
    45  
    46  	offset := uint(0)
    47  	for o := range offsets {
    48  		if o > offset {
    49  			offset = o
    50  		}
    51  	}
    52  	if offset >= 16 {
    53  		return StackArgs{OffsetToFirst: 16, Number: 1 + int((offset-16)/8)}
    54  	}
    55  	return StackArgs{OffsetToFirst: 0, Number: 0}
    56  }
    57  
    58  func parseCompanionFile(goCompanion, protoName string) ([]string, []string) {
    59  
    60  	gocode, err := readLines(goCompanion)
    61  	if err != nil {
    62  		panic(fmt.Sprintf("Failed to read companion go code: %v", err))
    63  	}
    64  
    65  	for _, goline := range gocode {
    66  
    67  		ok, args, rets, err := getGolangArgs(protoName, goline)
    68  		if err != nil {
    69  			panic(fmt.Sprintf("Error: %v", err))
    70  		} else if ok {
    71  			return args, rets
    72  		}
    73  	}
    74  
    75  	panic(fmt.Sprintf("Failed to find function prototype for %s", protoName))
    76  }
    77  
    78  var regexpFuncAndArgs = regexp.MustCompile(`^\s*func\s+([^\(]*)\(([^\)]*)\)(.*)`)
    79  var regexpReturnVals = regexp.MustCompile(`^\((.*)\)`)
    80  
    81  func getGolangArgs(protoName, goline string) (isFunc bool, args, rets []string, err error) {
    82  
    83  	// Search for name of function and arguments
    84  	if match := regexpFuncAndArgs.FindStringSubmatch(goline); len(match) > 2 {
    85  		if match[1] == "_"+protoName {
    86  
    87  			args, rets = []string{}, []string{}
    88  			if match[2] != "" {
    89  				for _, arg := range strings.Split(match[2], ",") {
    90  					args = append(args, strings.Fields(arg)[0])
    91  				}
    92  			}
    93  
    94  			trailer := strings.TrimSpace(match[3])
    95  			if len(trailer) > 0 {
    96  				// Trailing string found, search for return values
    97  				if rmatch := regexpReturnVals.FindStringSubmatch(trailer); len(rmatch) > 1 {
    98  					for _, ret := range strings.Split(rmatch[1], ",") {
    99  						rets = append(rets, strings.Fields(ret)[0])
   100  					}
   101  				} else {
   102  					return false, args, rets, errors.New(fmt.Sprintf("Badly formatted return argument (please use parenthesis and proper arguments naming): %s", trailer))
   103  				}
   104  
   105  			}
   106  
   107  			return true, args, rets, nil
   108  		}
   109  	}
   110  
   111  	return false, []string{}, []string{}, nil
   112  }
   113  
   114  func getTotalSizeOfArguments(argStart, argEnd int) uint {
   115  	// TODO: Test if correct for non 64-bit arguments
   116  	return uint((argEnd - argStart + 1) * 8)
   117  }
   118  
   119  func getTotalSizeOfArgumentsAndReturnValues(argStart, argEnd int, returnValues []string) uint {
   120  	// TODO: Test if correct for non 64-bit return values
   121  	return getTotalSizeOfArguments(argStart, argEnd) + uint(len(returnValues)*8)
   122  }