build: support comments in functions (#41)
This commit is contained in:
@@ -133,6 +133,11 @@ func (c *Context) Label(name string) {
|
||||
c.activefunc().AddLabel(ir.Label(name))
|
||||
}
|
||||
|
||||
// Comment adds comment lines to the active function.
|
||||
func (c *Context) Comment(lines ...string) {
|
||||
c.activefunc().AddComment(lines...)
|
||||
}
|
||||
|
||||
func (c *Context) activefunc() *ir.Function {
|
||||
if c.function == nil {
|
||||
c.adderrormessage("no active function")
|
||||
|
||||
@@ -125,5 +125,8 @@ func AllocLocal(size int) operand.Mem { return ctx.AllocLocal(size) }
|
||||
// Label adds a label to the active function.
|
||||
func Label(name string) { ctx.Label(name) }
|
||||
|
||||
// Comment adds comment lines to the active function.
|
||||
func Comment(lines ...string) { ctx.Comment(lines...) }
|
||||
|
||||
// ConstData builds a static data section containing just the given constant.
|
||||
func ConstData(name string, v operand.Constant) operand.Mem { return ctx.ConstData(name, v) }
|
||||
|
||||
19
ir/ir.go
19
ir/ir.go
@@ -20,6 +20,20 @@ type Label string
|
||||
|
||||
func (l Label) node() {}
|
||||
|
||||
// Comment represents a multi-line comment.
|
||||
type Comment struct {
|
||||
Lines []string
|
||||
}
|
||||
|
||||
func (c *Comment) node() {}
|
||||
|
||||
// NewComment builds a Comment consisting of the provided lines.
|
||||
func NewComment(lines ...string) *Comment {
|
||||
return &Comment{
|
||||
Lines: lines,
|
||||
}
|
||||
}
|
||||
|
||||
// Instruction is a single instruction in a function.
|
||||
type Instruction struct {
|
||||
Opcode string
|
||||
@@ -176,6 +190,11 @@ func (f *Function) AddLabel(l Label) {
|
||||
f.AddNode(l)
|
||||
}
|
||||
|
||||
// AddComment adds comment lines to f.
|
||||
func (f *Function) AddComment(lines ...string) {
|
||||
f.AddNode(NewComment(lines...))
|
||||
}
|
||||
|
||||
// AddNode appends a Node to f.
|
||||
func (f *Function) AddNode(n Node) {
|
||||
f.Nodes = append(f.Nodes, n)
|
||||
|
||||
38
pass/cfg.go
38
pass/cfg.go
@@ -11,27 +11,27 @@ import (
|
||||
// label name to the following instruction.
|
||||
func LabelTarget(fn *ir.Function) error {
|
||||
target := map[ir.Label]*ir.Instruction{}
|
||||
for idx := 0; idx < len(fn.Nodes); idx++ {
|
||||
// Is this a label?
|
||||
lbl, ok := fn.Nodes[idx].(ir.Label)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
// Check for a duplicate label.
|
||||
if _, found := target[lbl]; found {
|
||||
return fmt.Errorf("duplicate label \"%s\"", lbl)
|
||||
}
|
||||
// Advance to next node.
|
||||
if idx == len(fn.Nodes)-1 {
|
||||
return errors.New("function ends with label")
|
||||
}
|
||||
idx++
|
||||
// Should be an instruction.
|
||||
i, ok := fn.Nodes[idx].(*ir.Instruction)
|
||||
if !ok {
|
||||
var empty ir.Label
|
||||
pending := empty
|
||||
for _, node := range fn.Nodes {
|
||||
switch n := node.(type) {
|
||||
case ir.Label:
|
||||
if pending != empty {
|
||||
return errors.New("instruction should follow a label")
|
||||
}
|
||||
target[lbl] = i
|
||||
pending = n
|
||||
if _, found := target[pending]; found {
|
||||
return fmt.Errorf("duplicate label \"%s\"", pending)
|
||||
}
|
||||
case *ir.Instruction:
|
||||
if pending != empty {
|
||||
target[pending] = n
|
||||
pending = empty
|
||||
}
|
||||
}
|
||||
}
|
||||
if pending != empty {
|
||||
return errors.New("function ends with label")
|
||||
}
|
||||
fn.LabelTarget = target
|
||||
return nil
|
||||
|
||||
@@ -18,6 +18,7 @@ func TestLabelTarget(t *testing.T) {
|
||||
f := ir.NewFunction("happypath")
|
||||
for lbl, i := range expect {
|
||||
f.AddLabel(lbl)
|
||||
f.AddComment("comments should be ignored")
|
||||
f.AddInstruction(i)
|
||||
f.AddInstruction(&ir.Instruction{Opcode: "IDK"})
|
||||
}
|
||||
|
||||
@@ -84,6 +84,15 @@ func (p *goasm) function(f *ir.Function) {
|
||||
p.Printf(", %s\n", textsize(f))
|
||||
|
||||
w := p.tabwriter()
|
||||
clear := true
|
||||
flush := func() {
|
||||
w.Flush()
|
||||
w = p.tabwriter()
|
||||
if !clear {
|
||||
p.NL()
|
||||
clear = true
|
||||
}
|
||||
}
|
||||
for _, node := range f.Nodes {
|
||||
switch n := node.(type) {
|
||||
case *ir.Instruction:
|
||||
@@ -93,10 +102,15 @@ func (p *goasm) function(f *ir.Function) {
|
||||
fmt.Fprintf(w, "\t%s", joinOperands(n.Operands))
|
||||
}
|
||||
fmt.Fprint(w, "\n")
|
||||
clear = false
|
||||
case ir.Label:
|
||||
w.Flush()
|
||||
w = p.tabwriter()
|
||||
p.Printf("\n%s:\n", n)
|
||||
flush()
|
||||
p.Printf("%s:\n", n)
|
||||
case *ir.Comment:
|
||||
flush()
|
||||
for _, line := range n.Lines {
|
||||
p.Printf("\t// %s\n", line)
|
||||
}
|
||||
default:
|
||||
panic("unexpected node type")
|
||||
}
|
||||
|
||||
26
tests/fmt/asm.go
Normal file
26
tests/fmt/asm.go
Normal file
@@ -0,0 +1,26 @@
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
. "github.com/mmcloughlin/avo/build"
|
||||
. "github.com/mmcloughlin/avo/reg"
|
||||
)
|
||||
|
||||
func main() {
|
||||
TEXT("Formatting", NOSPLIT, "func()")
|
||||
Doc("Formatting contains various cases to test the formatter.")
|
||||
|
||||
ADDQ(R8, R8)
|
||||
Comment("One comment line between instructions.")
|
||||
ADDQ(R8, R8)
|
||||
|
||||
Comment("Comment before label.")
|
||||
Label("label")
|
||||
Comment("Comment after label.")
|
||||
ADDQ(R8, R8)
|
||||
|
||||
RET()
|
||||
|
||||
Generate()
|
||||
}
|
||||
16
tests/fmt/fmt.s
Normal file
16
tests/fmt/fmt.s
Normal file
@@ -0,0 +1,16 @@
|
||||
// Code generated by command: go run asm.go -out fmt.s -stubs stub.go. DO NOT EDIT.
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
// func Formatting()
|
||||
TEXT ·Formatting(SB), NOSPLIT, $0
|
||||
ADDQ R8, R8
|
||||
|
||||
// One comment line between instructions.
|
||||
ADDQ R8, R8
|
||||
|
||||
// Comment before label.
|
||||
label:
|
||||
// Comment after label.
|
||||
ADDQ R8, R8
|
||||
RET
|
||||
4
tests/fmt/gen.go
Normal file
4
tests/fmt/gen.go
Normal file
@@ -0,0 +1,4 @@
|
||||
// Package fmt tests assembly printer formatting.
|
||||
package fmt
|
||||
|
||||
//go:generate go run asm.go -out fmt.s -stubs stub.go
|
||||
6
tests/fmt/stub.go
Normal file
6
tests/fmt/stub.go
Normal file
@@ -0,0 +1,6 @@
|
||||
// Code generated by command: go run asm.go -out fmt.s -stubs stub.go. DO NOT EDIT.
|
||||
|
||||
package fmt
|
||||
|
||||
// Formatting contains various cases to test the formatter.
|
||||
func Formatting()
|
||||
Reference in New Issue
Block a user