github.com/consensys/gnark@v0.11.0/debug/debug.go (about)

     1  package debug
     2  
     3  import (
     4  	"path/filepath"
     5  	"runtime"
     6  	"strconv"
     7  	"strings"
     8  )
     9  
    10  func Stack() string {
    11  	var sbb strings.Builder
    12  	writeStack(&sbb)
    13  	return sbb.String()
    14  }
    15  
    16  type Location struct {
    17  	FunctionID int
    18  	Line       int64
    19  }
    20  
    21  type Function struct {
    22  	Name       string
    23  	SystemName string
    24  	Filename   string
    25  }
    26  
    27  func writeStack(sbb *strings.Builder, forceClean ...bool) {
    28  	// derived from: https://golang.org/pkg/runtime/#example_Frames
    29  	// we stop when func name == Define as it is where the gnark circuit code should start
    30  
    31  	// Ask runtime.Callers for up to 10 pcs
    32  	pc := make([]uintptr, 20)
    33  	n := runtime.Callers(3, pc)
    34  	if n == 0 {
    35  		// No pcs available. Stop now.
    36  		// This can happen if the first argument to runtime.Callers is large.
    37  		return
    38  	}
    39  	pc = pc[:n] // pass only valid pcs to runtime.CallersFrames
    40  	frames := runtime.CallersFrames(pc)
    41  	// Loop to get frames.
    42  	// A fixed number of pcs can expand to an indefinite number of Frames.
    43  	for {
    44  		frame, more := frames.Next()
    45  		fe := strings.Split(frame.Function, "/")
    46  		function := fe[len(fe)-1]
    47  		file := frame.File
    48  
    49  		if !Debug || (len(forceClean) > 1 && forceClean[0]) {
    50  			if strings.Contains(function, "runtime.gopanic") {
    51  				continue
    52  			}
    53  			if strings.Contains(function, "frontend.(*constraintSystem)") {
    54  				continue
    55  			}
    56  			if strings.Contains(frame.File, "test/engine.go") {
    57  				continue
    58  			}
    59  			if strings.Contains(frame.File, "gnark/frontend/cs") {
    60  				continue
    61  			}
    62  			file = filepath.Base(file)
    63  		}
    64  
    65  		sbb.WriteString(function)
    66  		sbb.WriteByte('\n')
    67  		sbb.WriteByte('\t')
    68  		sbb.WriteString(file)
    69  		sbb.WriteByte(':')
    70  		sbb.WriteString(strconv.Itoa(frame.Line))
    71  		sbb.WriteByte('\n')
    72  		if !more {
    73  			break
    74  		}
    75  		if strings.HasSuffix(function, "Define") {
    76  			break
    77  		}
    78  		if strings.HasSuffix(function, "callDeferred") {
    79  			break
    80  		}
    81  	}
    82  }