From 602bb5197c749ef848e12394ae4e686140064ca4 Mon Sep 17 00:00:00 2001 From: Michael McLoughlin Date: Sat, 5 Jan 2019 18:18:49 -0800 Subject: [PATCH] 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 --- README.md | 4 +-- ast.go | 5 +-- attr.go => attr/attr.go | 3 +- attr_test.go => attr/attr_test.go | 2 +- build/context.go | 11 ++++--- build/global.go | 13 ++++---- build/pseudo.go | 4 +-- examples/data/asm.go | 2 +- examples/dot/asm.go | 8 ++--- examples/fnv1a/README.md | 4 +-- examples/fnv1a/asm.go | 4 +-- examples/stadtx/asm.go | 52 +++++++++++++++---------------- examples/sum/README.md | 4 +-- examples/sum/asm.go | 4 +-- pass/textflag.go | 3 +- printer/goasm_test.go | 4 +-- tests/textflag/make_attrtest.go | 12 +++---- 17 files changed, 71 insertions(+), 68 deletions(-) rename attr.go => attr/attr.go (97%) rename attr_test.go => attr/attr_test.go (98%) diff --git a/README.md b/README.md index 27a18066..fd6d545f 100644 --- a/README.md +++ b/README.md @@ -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() diff --git a/ast.go b/ast.go index ca3e799e..0dd51c7c 100644 --- a/ast.go +++ b/ast.go @@ -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 } diff --git a/attr.go b/attr/attr.go similarity index 97% rename from attr.go rename to attr/attr.go index 3fb0932e..9173773f 100644 --- a/attr.go +++ b/attr/attr.go @@ -1,4 +1,5 @@ -package avo +// Package attr provides attributes for text and data sections. +package attr import ( "fmt" diff --git a/attr_test.go b/attr/attr_test.go similarity index 98% rename from attr_test.go rename to attr/attr_test.go index e16e7195..99bb9732 100644 --- a/attr_test.go +++ b/attr/attr_test.go @@ -1,4 +1,4 @@ -package avo +package attr import "testing" diff --git a/build/context.go b/build/context.go index af1bbf42..a895d1aa 100644 --- a/build/context.go +++ b/build/context.go @@ -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 } diff --git a/build/global.go b/build/global.go index 8c86637e..06f0da40 100644 --- a/build/global.go +++ b/build/global.go @@ -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) } diff --git a/build/pseudo.go b/build/pseudo.go index d4e87e71..69aeed38 100644 --- a/build/pseudo.go +++ b/build/pseudo.go @@ -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 } diff --git a/examples/data/asm.go b/examples/data/asm.go index 538a5a2d..50736fd0 100644 --- a/examples/data/asm.go +++ b/examples/data/asm.go @@ -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" ) diff --git a/examples/dot/asm.go b/examples/dot/asm.go index ceaa664c..365f3532 100644 --- a/examples/dot/asm.go +++ b/examples/dot/asm.go @@ -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]) } diff --git a/examples/fnv1a/README.md b/examples/fnv1a/README.md index 62ed5046..78429201 100644 --- a/examples/fnv1a/README.md +++ b/examples/fnv1a/README.md @@ -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() diff --git a/examples/fnv1a/asm.go b/examples/fnv1a/asm.go index 07c7dc1b..fdb10fd1 100644 --- a/examples/fnv1a/asm.go +++ b/examples/fnv1a/asm.go @@ -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() diff --git a/examples/stadtx/asm.go b/examples/stadtx/asm.go index 81dd73d8..35bfdabc 100644 --- a/examples/stadtx/asm.go +++ b/examples/stadtx/asm.go @@ -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 // diff --git a/examples/sum/README.md b/examples/sum/README.md index d2a5984d..22ce1f80 100644 --- a/examples/sum/README.md +++ b/examples/sum/README.md @@ -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() diff --git a/examples/sum/asm.go b/examples/sum/asm.go index 3ec57fb4..42910f94 100644 --- a/examples/sum/asm.go +++ b/examples/sum/asm.go @@ -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() diff --git a/pass/textflag.go b/pass/textflag.go index 6d4990c9..e2ecd0b6 100644 --- a/pass/textflag.go +++ b/pass/textflag.go @@ -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 diff --git a/printer/goasm_test.go b/printer/goasm_test.go index f8cc2504..408b6a35 100644 --- a/printer/goasm_test.go +++ b/printer/goasm_test.go @@ -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{ diff --git a/tests/textflag/make_attrtest.go b/tests/textflag/make_attrtest.go index 2ebcfbff..71d70b94 100644 --- a/tests/textflag/make_attrtest.go +++ b/tests/textflag/make_attrtest.go @@ -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")