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 }