package verbose import ( "fmt" "slices" "strings" "unicode" "git.urbach.dev/cli/q/src/codegen" "git.urbach.dev/cli/q/src/core" "git.urbach.dev/cli/q/src/ssa" "git.urbach.dev/go/color/ansi" ) // SSA shows the SSA IR. func SSA(env *core.Environment, pattern string) { for f := range env.LiveFunctions() { if filter(f.FullName, pattern) { continue } tmpColor := ansi.Green tmpPrefix := "α" pointerToName := make(map[string]string, len(f.Steps)) pointerToName[fmt.Sprintf("%p", ssa.Undefined)] = "?" for _, step := range f.Steps { pointerToName[fmt.Sprintf("%p", step.Value)] = fmt.Sprintf("%s%d", tmpPrefix, step.Index) } ansi.Yellow.Println(f.FullName + ":") for _, step := range f.Steps { _, isLabel := step.Value.(*codegen.Label) if isLabel { fmt.Printf("\n%s:", step.Value.String()) for _, pre := range step.Block.Predecessors { ansi.Dim.Print(" ⇠ ") ansi.Dim.Print(pre) } fmt.Println() continue } ansi.Dim.Print(" ") ansi.Dim.Printf("%s%-2d", tmpPrefix, step.Index) ansi.Dim.Print(" = ") value := step.Value.String() _, isInt := step.Value.(*ssa.Int) if isInt { ansi.Cyan.Print(value) } else { pos := strings.Index(value, "0x") for { if pos == -1 { fmt.Print(value) break } end := strings.IndexFunc(value[pos+2:], func(r rune) bool { return !unicode.Is(unicode.Hex_Digit, r) }) if end == -1 { end = len(value) - pos - 2 } name := pointerToName[value[pos:pos+2+end]] fmt.Print(value[:pos]) tmpColor.Print(name) value = value[pos+2+end:] pos = strings.Index(value, "0x") } } ansi.Dim.Printf(" %s %s ", step.Value.Type().Name(), step.Register) if step.Block.IsIdentified(step.Value) { ansi.Dim.Print("id: ") for identifier := range step.Block.IdentifiersFor(step.Value) { ansi.Dim.Printf("%s ", identifier) } } if len(step.Live) > 0 { ansi.Dim.Printf("live: ") slices.SortStableFunc(step.Live, func(a *codegen.Step, b *codegen.Step) int { return int(a.Index - b.Index) }) for _, live := range step.Live { ansi.Dim.Printf("%s%d ", tmpPrefix, live.Index) } } fmt.Println() } fmt.Println() } }