blob: 677c3fca48916003841e40b7034738dfbf3bc212 [file]
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ssa
import (
"fmt"
"html"
"strings"
)
func (v *Value) HTML() string {
// TODO: Using the value ID as the class ignores the fact
// that value IDs get recycled and that some values
// are transmuted into other values.
s := v.String()
return fmt.Sprintf("<span class=\"%s ssa-value\">%s</span>", s, s)
}
func (v *Value) LongHTML() string {
// TODO: Any intra-value formatting?
// I'm wary of adding too much visual noise,
// but a little bit might be valuable.
// We already have visual noise in the form of punctuation
// maybe we could replace some of that with formatting.
s := fmt.Sprintf("<span class=\"%s ssa-long-value\">", v.String())
linenumber := "<span class=\"no-line-number\">(?)</span>"
if v.Pos.IsKnown() {
linenumber = fmt.Sprintf("<span class=\"l%v line-number\">(%s)</span>", v.Pos.LineNumber(), v.Pos.LineNumberHTML())
}
s += fmt.Sprintf("%s %s = %s", v.HTML(), linenumber, v.Op.String())
s += " &lt;" + html.EscapeString(v.Type.String()) + "&gt;"
s += html.EscapeString(v.AuxString())
for _, a := range v.Args {
s += fmt.Sprintf(" %s", a.HTML())
}
r := v.Block.Func.RegAlloc
if int(v.ID) < len(r) && r[v.ID] != nil {
s += " : " + html.EscapeString(r[v.ID].String())
}
if reg := v.Block.Func.TempRegs[v.ID]; reg != nil {
s += " tmp=" + reg.String()
}
var names []string
for name, values := range v.Block.Func.NamedValues {
for _, value := range values {
if value == v {
names = append(names, name.String())
break // drop duplicates.
}
}
}
if len(names) != 0 {
s += " (" + strings.Join(names, ", ") + ")"
}
s += "</span>"
return s
}
func (b *Block) HTML() string {
// TODO: Using the value ID as the class ignores the fact
// that value IDs get recycled and that some values
// are transmuted into other values.
s := html.EscapeString(b.String())
return fmt.Sprintf("<span class=\"%s ssa-block\">%s</span>", s, s)
}
func (b *Block) LongHTML() string {
// TODO: improve this for HTML?
s := fmt.Sprintf("<span class=\"%s ssa-block\">%s</span>", html.EscapeString(b.String()), html.EscapeString(b.Kind.String()))
if b.Aux != nil {
s += html.EscapeString(fmt.Sprintf(" {%v}", b.Aux))
}
if t := b.AuxIntString(); t != "" {
s += html.EscapeString(fmt.Sprintf(" [%v]", t))
}
for _, c := range b.ControlValues() {
s += fmt.Sprintf(" %s", c.HTML())
}
if len(b.Succs) > 0 {
s += " &#8594;" // right arrow
for _, e := range b.Succs {
c := e.B
s += " " + c.HTML()
}
}
switch b.Likely {
case BranchUnlikely:
s += " (unlikely)"
case BranchLikely:
s += " (likely)"
}
if b.Pos.IsKnown() {
// TODO does not begin to deal with the full complexity of line numbers.
// Maybe we want a string/slice instead, of outer-inner when inlining.
s += fmt.Sprintf(" <span class=\"l%v line-number\">(%s)</span>", b.Pos.LineNumber(), b.Pos.LineNumberHTML())
}
return s
}
func (b *Block) UnlikelyIndex() int {
switch b.Likely {
case BranchLikely:
return 1
case BranchUnlikely:
return 0
}
return -1
}