build: unify Label function signatures

The Context.Label method and LABEL global function did not agree. Also
breaks the convention I'd like to set that capitalized functions must
agree with existing Go assembly syntax.

To help avoid a conflict with `avo.Label`, attributes were moved to
their own package.

Fixes #35
This commit is contained in:
Michael McLoughlin
2019-01-05 18:18:49 -08:00
parent 87ffa6823a
commit 602bb5197c
17 changed files with 71 additions and 68 deletions

View File

@@ -105,14 +105,14 @@ func main() {
n := Load(Param("xs").Len(), GP64())
s := GP64()
XORQ(s, s)
LABEL("loop")
Label("loop")
CMPQ(n, Imm(0))
JE(LabelRef("done"))
ADDQ(Mem{Base: ptr}, s)
ADDQ(Imm(8), ptr)
DECQ(n)
JMP(LabelRef("loop"))
LABEL("done")
Label("done")
Store(s, ReturnIndex(0))
RET()
Generate()

5
ast.go
View File

@@ -3,6 +3,7 @@ package avo
import (
"errors"
"github.com/mmcloughlin/avo/attr"
"github.com/mmcloughlin/avo/buildtags"
"github.com/mmcloughlin/avo/gotypes"
"github.com/mmcloughlin/avo/operand"
@@ -128,7 +129,7 @@ func (f *File) Functions() []*Function {
// Function represents an assembly function.
type Function struct {
Name string
Attributes Attribute
Attributes attr.Attribute
Doc []string
Signature *gotypes.Signature
LocalSize int
@@ -236,7 +237,7 @@ func (d Datum) Overlaps(other Datum) bool {
// Global represents a DATA section.
type Global struct {
Symbol operand.Symbol
Attributes Attribute
Attributes attr.Attribute
Data []Datum
Size int
}

View File

@@ -1,4 +1,5 @@
package avo
// Package attr provides attributes for text and data sections.
package attr
import (
"fmt"

View File

@@ -1,4 +1,4 @@
package avo
package attr
import "testing"

View File

@@ -5,6 +5,7 @@ import (
"go/types"
"github.com/mmcloughlin/avo"
"github.com/mmcloughlin/avo/attr"
"github.com/mmcloughlin/avo/buildtags"
"github.com/mmcloughlin/avo/gotypes"
"github.com/mmcloughlin/avo/operand"
@@ -90,7 +91,7 @@ func (c *Context) Doc(lines ...string) {
}
// Attributes sets function attributes for the currently active function.
func (c *Context) Attributes(a avo.Attribute) {
func (c *Context) Attributes(a attr.Attribute) {
c.activefunc().Attributes = a
}
@@ -124,12 +125,12 @@ func (c *Context) AllocLocal(size int) operand.Mem {
// Instruction adds an instruction to the active function.
func (c *Context) Instruction(i *avo.Instruction) {
c.activefunc().AddNode(i)
c.activefunc().AddInstruction(i)
}
// Label adds a label to the active function.
func (c *Context) Label(l avo.Label) {
c.activefunc().AddLabel(l)
func (c *Context) Label(name string) {
c.activefunc().AddLabel(avo.Label(name))
}
func (c *Context) activefunc() *avo.Function {
@@ -150,7 +151,7 @@ func (c *Context) StaticGlobal(name string) operand.Mem {
}
// DataAttributes sets the attributes on the current active global data section.
func (c *Context) DataAttributes(a avo.Attribute) {
func (c *Context) DataAttributes(a attr.Attribute) {
c.activeglobal().Attributes = a
}

View File

@@ -4,13 +4,12 @@ import (
"flag"
"os"
"github.com/mmcloughlin/avo/attr"
"github.com/mmcloughlin/avo/buildtags"
"github.com/mmcloughlin/avo/gotypes"
"github.com/mmcloughlin/avo/operand"
"github.com/mmcloughlin/avo/reg"
"github.com/mmcloughlin/avo"
)
// ctx provides a global build context.
@@ -22,11 +21,8 @@ func TEXT(name, signature string) {
ctx.SignatureExpr(signature)
}
// LABEL adds a label to the active function.
func LABEL(name string) { ctx.Label(avo.Label(name)) }
// GLOBL declares a new static global data section with the given attributes.
func GLOBL(name string, a avo.Attribute) operand.Mem {
func GLOBL(name string, a attr.Attribute) operand.Mem {
// TODO(mbm): should this be static?
g := ctx.StaticGlobal(name)
ctx.DataAttributes(a)
@@ -119,11 +115,14 @@ func Store(src reg.Register, dst gotypes.Component) { ctx.Store(src, dst) }
func Doc(lines ...string) { ctx.Doc(lines...) }
// Attributes sets function attributes for the currently active function.
func Attributes(a avo.Attribute) { ctx.Attributes(a) }
func Attributes(a attr.Attribute) { ctx.Attributes(a) }
// AllocLocal allocates size bytes in the stack of the currently active function.
// Returns a reference to the base pointer for the newly allocated region.
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) }
// 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) }

View File

@@ -1,7 +1,7 @@
package build
import (
"github.com/mmcloughlin/avo"
"github.com/mmcloughlin/avo/attr"
"github.com/mmcloughlin/avo/operand"
"github.com/mmcloughlin/avo/reg"
@@ -57,7 +57,7 @@ func (c *Context) Store(src reg.Register, dst gotypes.Component) {
// ConstData builds a static data section containing just the given constant.
func (c *Context) ConstData(name string, v operand.Constant) operand.Mem {
g := c.StaticGlobal(name)
c.DataAttributes(avo.RODATA | avo.NOPTR)
c.DataAttributes(attr.RODATA | attr.NOPTR)
c.AppendDatum(v)
return g
}

View File

@@ -5,7 +5,7 @@ package main
import (
"math"
. "github.com/mmcloughlin/avo"
. "github.com/mmcloughlin/avo/attr"
. "github.com/mmcloughlin/avo/build"
. "github.com/mmcloughlin/avo/operand"
)

View File

@@ -30,7 +30,7 @@ func main() {
// Loop over blocks and process them with vector instructions.
blockitems := 8 * unroll
blocksize := 4 * blockitems
LABEL("blockloop")
Label("blockloop")
CMPQ(n, U32(blockitems))
JL(LabelRef("tail"))
@@ -55,11 +55,11 @@ func main() {
JMP(LabelRef("blockloop"))
// Process any trailing entries.
LABEL("tail")
Label("tail")
tail := XMM()
VXORPS(tail, tail, tail)
LABEL("tailloop")
Label("tailloop")
CMPQ(n, U32(0))
JE(LabelRef("reduce"))
@@ -73,7 +73,7 @@ func main() {
JMP(LabelRef("tailloop"))
// Reduce the lanes to one.
LABEL("reduce")
Label("reduce")
for i := 1; i < unroll; i++ {
VADDPS(acc[0], acc[i], acc[0])
}

View File

@@ -20,7 +20,7 @@ func main() {
p := GP64()
MOVQ(Imm(Prime), p)
LABEL("loop")
Label("loop")
CMPQ(n, Imm(0))
JE(LabelRef("done"))
b := GP64()
@@ -31,7 +31,7 @@ func main() {
DECQ(n)
JMP(LabelRef("loop"))
LABEL("done")
Label("done")
Store(h, ReturnIndex(0))
RET()
Generate()

View File

@@ -24,7 +24,7 @@ func main() {
p := GP64()
MOVQ(Imm(Prime), p)
LABEL("loop")
Label("loop")
CMPQ(n, Imm(0))
JE(LabelRef("done"))
b := GP64()
@@ -35,7 +35,7 @@ func main() {
DECQ(n)
JMP(LabelRef("loop"))
LABEL("done")
Label("done")
Store(h, ReturnIndex(0))
RET()
Generate()

View File

@@ -76,7 +76,7 @@ func main() {
JE(LabelRef(labels[i])) // JE(labels[i])
} //
for i := 3; i > 0; i-- { // for i in range(3, 0, -1):
LABEL(labels[i]) // LABEL(labels[i])
Label(labels[i]) // Label(labels[i])
r := GP64() // r = GeneralPurposeRegister64()
MOVQ(Mem{Base: ptr}, r) // MOV(r, [reg_ptr])
imul(k3U64, r) // imul(r, k3U64)
@@ -88,7 +88,7 @@ func main() {
ADDQ(U32(8), ptr) // ADD(reg_ptr,8)
SUBQ(U32(8), n) // SUB(reg_ptr_len,8)
} //
LABEL(labels[0]) // LABEL(labels[0])
Label(labels[0]) // Label(labels[0])
//
labels = makelabels("shortTail", 8) // labels = [Label("shortTail%d" % i) for i in range(8)]
//
@@ -102,49 +102,49 @@ func main() {
//
ch := GP64() // reg_ch = GeneralPurposeRegister64()
//
LABEL(labels[7]) // LABEL(labels[7])
Label(labels[7]) // Label(labels[7])
MOVBQZX(Mem{Base: ptr, Disp: 6}, ch) // MOVZX(reg_ch, byte[reg_ptr+6])
SHLQ(U8(32), ch) // SHL(reg_ch, 32)
ADDQ(ch, v0) // ADD(reg_v0, reg_ch)
//
LABEL(labels[6]) // LABEL(labels[6])
Label(labels[6]) // Label(labels[6])
MOVBQZX(Mem{Base: ptr, Disp: 5}, ch) // MOVZX(reg_ch, byte[reg_ptr+5])
SHLQ(U8(48), ch) // SHL(reg_ch, 48)
ADDQ(ch, v1) // ADD(reg_v1, reg_ch)
//
LABEL(labels[5]) // LABEL(labels[5])
Label(labels[5]) // Label(labels[5])
MOVBQZX(Mem{Base: ptr, Disp: 4}, ch) // MOVZX(reg_ch, byte[reg_ptr+4])
SHLQ(U8(16), ch) // SHL(reg_ch, 16)
ADDQ(ch, v0) // ADD(reg_v0, reg_ch)
//
LABEL(labels[4]) // LABEL(labels[4])
Label(labels[4]) // Label(labels[4])
// XOR(reg_ch, reg_ch)
MOVLQZX(Mem{Base: ptr}, ch) // MOV(reg_ch.as_dword, dword[reg_ptr])
ADDQ(ch, v1) // ADD(reg_v1, reg_ch)
//
JMP(LabelRef(after)) // JMP(after)
//
LABEL(labels[3]) // LABEL(labels[3])
Label(labels[3]) // Label(labels[3])
MOVBQZX(Mem{Base: ptr, Disp: 2}, ch) // MOVZX(reg_ch, byte[reg_ptr+2])
SHLQ(U8(48), ch) // SHL(reg_ch, 48)
ADDQ(ch, v0) // ADD(reg_v0, reg_ch)
//
LABEL(labels[2]) // LABEL(labels[2])
Label(labels[2]) // Label(labels[2])
// XOR(reg_ch, reg_ch)
MOVWQZX(Mem{Base: ptr}, ch) // MOV(reg_ch.as_word, word[reg_ptr])
ADDQ(ch, v1) // ADD(reg_v1, reg_ch)
//
JMP(LabelRef(after)) // JMP(after)
//
LABEL(labels[1]) // LABEL(labels[1])
Label(labels[1]) // Label(labels[1])
MOVBQZX(Mem{Base: ptr}, ch) // MOVZX(reg_ch, byte[reg_ptr])
ADDQ(ch, v0) // ADD(reg_v0, reg_ch)
//
LABEL(labels[0]) // LABEL(labels[0])
Label(labels[0]) // Label(labels[0])
RORQ(U8(32), v1) // ROR(reg_v1, 32)
XORQ(U32(0xff), v1) // XOR(reg_v1, 0xFF)
//
LABEL(after) // LABEL(after)
Label(after) // Label(after)
//
XORQ(v0, v1) // XOR(reg_v1, reg_v0)
//
@@ -187,7 +187,7 @@ func main() {
Store(v0, ReturnIndex(0))
RET() // RETURN(reg_v0)
//
LABEL(long) // LABEL(coreLong)
Label(long) // Label(coreLong)
//
v2 := GP64() // reg_v2 = GeneralPurposeRegister64()
v3 := GP64() // reg_v3 = GeneralPurposeRegister64()
@@ -208,7 +208,7 @@ func main() {
//
r := GP64() // r = GeneralPurposeRegister64()
loop := "block" // with Loop() as loop:
LABEL(loop)
Label(loop)
MOVQ(Mem{Base: ptr}, r) // MOV(r, [reg_ptr])
imul(k2U32, r) // imul(r, k2U32)
ADDQ(r, v0) // ADD(reg_v0, r)
@@ -253,7 +253,7 @@ func main() {
CMPQ(u64s, U32(i)) // CMP(reg_u64s, i)
JE(LabelRef(labels[i])) // JE(labels[i])
} //
LABEL(labels[3]) // LABEL(labels[3])
Label(labels[3]) // Label(labels[3])
//
MOVQ(Mem{Base: ptr}, r) // MOV(r, [reg_ptr])
imul(k2U32, r) // imul(r, k2U32)
@@ -263,7 +263,7 @@ func main() {
ADDQ(U32(8), ptr) // ADD(reg_ptr, 8)
SUBQ(U32(8), n) // SUB(reg_ptr_len, 8)
//
LABEL(labels[2]) // LABEL(labels[2])
Label(labels[2]) // Label(labels[2])
//
MOVQ(Mem{Base: ptr}, r) // MOV(r, [reg_ptr])
imul(k3U32, r) // imul(r, k3U32)
@@ -273,7 +273,7 @@ func main() {
ADDQ(U32(8), ptr) // ADD(reg_ptr, 8)
SUBQ(U32(8), n) // SUB(reg_ptr_len, 8)
//
LABEL(labels[1]) // LABEL(labels[1])
Label(labels[1]) // Label(labels[1])
//
MOVQ(Mem{Base: ptr}, r) // MOV(r, [reg_ptr])
imul(k4U32, r) // imul(r, k4U32)
@@ -283,7 +283,7 @@ func main() {
ADDQ(U32(8), ptr) // ADD(reg_ptr, 8)
SUBQ(U32(8), n) // SUB(reg_ptr_len, 8)
//
LABEL(labels[0]) // LABEL(labels[0])
Label(labels[0]) // Label(labels[0])
//
RORQ(U8(11), v3) // ROR(reg_v3, 11)
SUBQ(v1, v3) // SUB(reg_v3, reg_v1)
@@ -304,11 +304,11 @@ func main() {
//
// reg_ch = GeneralPurposeRegister64()
//
LABEL(labels[7]) // LABEL(labels[7])
Label(labels[7]) // Label(labels[7])
MOVBQZX(Mem{Base: ptr, Disp: 6}, ch) // MOVZX(reg_ch, byte[reg_ptr+6])
ADDQ(ch, v1) // ADD(reg_v1, reg_ch)
//
LABEL(labels[6]) // LABEL(labels[6])
Label(labels[6]) // Label(labels[6])
// XOR(reg_ch, reg_ch)
MOVWQZX(Mem{Base: ptr, Disp: 4}, ch) // MOV(reg_ch.as_word, word[reg_ptr + 4])
ADDQ(ch, v2) // ADD(reg_v2, reg_ch)
@@ -316,37 +316,37 @@ func main() {
ADDQ(ch, v3) // ADD(reg_v3, reg_ch)
JMP(LabelRef(after)) // JMP(after)
//
LABEL(labels[5]) // LABEL(labels[5])
Label(labels[5]) // Label(labels[5])
MOVBQZX(Mem{Base: ptr, Disp: 4}, ch) // MOVZX(reg_ch, byte[reg_ptr+4])
ADDQ(ch, v1) // ADD(reg_v1, reg_ch)
//
LABEL(labels[4]) // LABEL(labels[4])
Label(labels[4]) // Label(labels[4])
// XOR(reg_ch, reg_ch)
MOVLQZX(Mem{Base: ptr}, ch) // MOV(reg_ch.as_dword, dword[reg_ptr])
ADDQ(ch, v2) // ADD(reg_v2, reg_ch)
//
JMP(LabelRef(after)) // JMP(after)
//
LABEL(labels[3]) // LABEL(labels[3])
Label(labels[3]) // Label(labels[3])
MOVBQZX(Mem{Base: ptr, Disp: 2}, ch) // MOVZX(reg_ch, byte[reg_ptr+2])
ADDQ(ch, v3) // ADD(reg_v3, reg_ch)
//
LABEL(labels[2]) // LABEL(labels[2])
Label(labels[2]) // Label(labels[2])
// XOR(reg_ch, reg_ch)
MOVWQZX(Mem{Base: ptr}, ch) // MOV(reg_ch.as_word, word[reg_ptr])
ADDQ(ch, v1) // ADD(reg_v1, reg_ch)
//
JMP(LabelRef(after)) // JMP(after)
//
LABEL(labels[1]) // LABEL(labels[1])
Label(labels[1]) // Label(labels[1])
MOVBQZX(Mem{Base: ptr}, ch) // MOVZX(reg_ch, byte[reg_ptr])
ADDQ(ch, v2) // ADD(reg_v2, reg_ch)
//
LABEL(labels[0]) // LABEL(labels[0])
Label(labels[0]) // Label(labels[0])
ROLQ(U8(32), v3) // ROL(reg_v3, 32)
XORQ(U32(0xff), v3) // XOR(reg_v3, 0xFF)
//
LABEL(after) // LABEL(after)
Label(after) // Label(after)
//
// ## finalize
//

View File

@@ -11,14 +11,14 @@ func main() {
n := Load(Param("xs").Len(), GP64())
s := GP64()
XORQ(s, s)
LABEL("loop")
Label("loop")
CMPQ(n, Imm(0))
JE(LabelRef("done"))
ADDQ(Mem{Base: ptr}, s)
ADDQ(Imm(8), ptr)
DECQ(n)
JMP(LabelRef("loop"))
LABEL("done")
Label("done")
Store(s, ReturnIndex(0))
RET()
Generate()

View File

@@ -14,14 +14,14 @@ func main() {
n := Load(Param("xs").Len(), GP64())
s := GP64()
XORQ(s, s)
LABEL("loop")
Label("loop")
CMPQ(n, Imm(0))
JE(LabelRef("done"))
ADDQ(Mem{Base: ptr}, s)
ADDQ(Imm(8), ptr)
DECQ(n)
JMP(LabelRef("loop"))
LABEL("done")
Label("done")
Store(s, ReturnIndex(0))
RET()
Generate()

View File

@@ -2,6 +2,7 @@ package pass
import (
"github.com/mmcloughlin/avo"
"github.com/mmcloughlin/avo/attr"
)
// IncludeTextFlagHeader includes textflag.h if necessary.
@@ -26,7 +27,7 @@ func IncludeTextFlagHeader(f *avo.File) error {
// requirestextflags returns whether the file uses flags in the textflags.h header.
func requirestextflags(f *avo.File) bool {
for _, s := range f.Sections {
var a avo.Attribute
var a attr.Attribute
switch s := s.(type) {
case *avo.Function:
a = s.Attributes

View File

@@ -3,7 +3,7 @@ package printer_test
import (
"testing"
"github.com/mmcloughlin/avo"
"github.com/mmcloughlin/avo/attr"
"github.com/mmcloughlin/avo/build"
"github.com/mmcloughlin/avo/printer"
"github.com/mmcloughlin/avo/reg"
@@ -47,7 +47,7 @@ func TestTextDecl(t *testing.T) {
ctx.Function("withattr")
ctx.SignatureExpr("func()")
ctx.Attributes(avo.NOSPLIT | avo.TLSBSS)
ctx.Attributes(attr.NOSPLIT | attr.TLSBSS)
ctx.RET()
AssertPrintsLines(t, ctx, printer.NewGoAsm, []string{

View File

@@ -13,7 +13,7 @@ import (
"path/filepath"
"runtime"
"github.com/mmcloughlin/avo"
"github.com/mmcloughlin/avo/attr"
)
var (
@@ -22,25 +22,25 @@ var (
num = flag.Int("num", 32, "number of attributes to generate")
)
func GenerateAttributes(n int) []avo.Attribute {
as := make([]avo.Attribute, 0, n)
func GenerateAttributes(n int) []attr.Attribute {
as := make([]attr.Attribute, 0, n)
// Include each bitlevel.
for i := 0; i < 16 && i < n; i++ {
a := avo.Attribute(1 << uint(i))
a := attr.Attribute(1 << uint(i))
as = append(as, a)
}
// Add randomly generated attributes.
for len(as) < n {
a := avo.Attribute(rand.Uint32())
a := attr.Attribute(rand.Uint32())
as = append(as, a)
}
return as
}
func PrintAttributesTest(w io.Writer, as []avo.Attribute) {
func PrintAttributesTest(w io.Writer, as []attr.Attribute) {
_, self, _, _ := runtime.Caller(0)
fmt.Fprintf(w, "// Code generated by %s. DO NOT EDIT.\n\n", filepath.Base(self))
fmt.Fprintf(w, "#include \"textflag.h\"\n\n")