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 }