From e364d6398ed1fec9c559067cded527986041e102 Mon Sep 17 00:00:00 2001 From: Michael McLoughlin Date: Sun, 30 Dec 2018 23:35:49 -0800 Subject: [PATCH] ast,build: add Attributes fields to Function and Global Updates #2 --- ast.go | 19 +++++++++++-------- build/context.go | 4 ++++ build/global.go | 3 ++- examples/add/add.s | 2 +- examples/args/args.s | 34 +++++++++++++++++----------------- examples/complex/complex.s | 6 +++--- examples/data/data.s | 2 +- examples/dot/dot.s | 2 +- examples/fnv1a/fnv1a.s | 2 +- examples/geohash/geohash.s | 2 +- examples/returns/returns.s | 10 +++++----- examples/sha1/sha1.s | 2 +- examples/stadtx/stadtx.s | 2 +- examples/sum/sum.s | 2 +- printer/goasm.go | 24 +++++++++++++++++++++--- printer/goasm_test.go | 18 ++++++++++++++---- tests/cast/cast.s | 2 +- 17 files changed, 86 insertions(+), 50 deletions(-) diff --git a/ast.go b/ast.go index c2284055..e852dfed 100644 --- a/ast.go +++ b/ast.go @@ -117,10 +117,11 @@ func (f *File) Functions() []*Function { // Function represents an assembly function. type Function struct { - Name string - Doc []string - Signature *gotypes.Signature - LocalSize int + Name string + Attributes Attribute + Doc []string + Signature *gotypes.Signature + LocalSize int Nodes []Node @@ -213,14 +214,16 @@ func (d Datum) Overlaps(other Datum) bool { } type Global struct { - Symbol operand.Symbol - Data []Datum - Size int + Symbol operand.Symbol + Attributes Attribute + Data []Datum + Size int } func NewGlobal(sym operand.Symbol) *Global { return &Global{ - Symbol: sym, + Symbol: sym, + Attributes: RODATA, } } diff --git a/build/context.go b/build/context.go index 237d0906..75a11b78 100644 --- a/build/context.go +++ b/build/context.go @@ -55,6 +55,10 @@ func (c *Context) Doc(lines ...string) { c.activefunc().Doc = lines } +func (c *Context) Attributes(a avo.Attribute) { + c.activefunc().Attributes = a +} + func (c *Context) Signature(s *gotypes.Signature) { c.activefunc().SetSignature(s) } diff --git a/build/global.go b/build/global.go index 11632b6b..03e8847e 100644 --- a/build/global.go +++ b/build/global.go @@ -58,7 +58,8 @@ func ReturnIndex(i int) gotypes.Component { return ctx.ReturnIndex(i) } func Load(src gotypes.Component, dst reg.Register) reg.Register { return ctx.Load(src, dst) } func Store(src reg.Register, dst gotypes.Component) { ctx.Store(src, dst) } -func Doc(lines ...string) { ctx.Doc(lines...) } +func Doc(lines ...string) { ctx.Doc(lines...) } +func Attributes(a avo.Attribute) { ctx.Attributes(a) } func AllocLocal(size int) operand.Mem { return ctx.AllocLocal(size) } diff --git a/examples/add/add.s b/examples/add/add.s index 5d867411..aad83ce4 100644 --- a/examples/add/add.s +++ b/examples/add/add.s @@ -3,7 +3,7 @@ #include "textflag.h" // func Add(x uint64, y uint64) uint64 -TEXT ·Add(SB), 0, $0-24 +TEXT ·Add(SB), $0-24 MOVQ x(FP), AX MOVQ y+8(FP), CX ADDQ AX, CX diff --git a/examples/args/args.s b/examples/args/args.s index 8e94018b..9a881f31 100644 --- a/examples/args/args.s +++ b/examples/args/args.s @@ -3,103 +3,103 @@ #include "textflag.h" // func StringLen(s string) int -TEXT ·StringLen(SB), 0, $0-24 +TEXT ·StringLen(SB), $0-24 MOVQ s_len+8(FP), AX MOVQ AX, ret+16(FP) RET // func SliceLen(s []int) int -TEXT ·SliceLen(SB), 0, $0-32 +TEXT ·SliceLen(SB), $0-32 MOVQ s_len+8(FP), AX MOVQ AX, ret+24(FP) RET // func SliceCap(s []int) int -TEXT ·SliceCap(SB), 0, $0-32 +TEXT ·SliceCap(SB), $0-32 MOVQ s_cap+16(FP), AX MOVQ AX, ret+24(FP) RET // func ArrayThree(a [7]uint64) uint64 -TEXT ·ArrayThree(SB), 0, $0-64 +TEXT ·ArrayThree(SB), $0-64 MOVQ a_3+24(FP), AX MOVQ AX, ret+56(FP) RET // func FieldByte(s Struct) byte -TEXT ·FieldByte(SB), 0, $0-177 +TEXT ·FieldByte(SB), $0-177 MOVB s_Byte(FP), AL MOVB AL, ret+176(FP) RET // func FieldInt8(s Struct) int8 -TEXT ·FieldInt8(SB), 0, $0-177 +TEXT ·FieldInt8(SB), $0-177 MOVB s_Int8+1(FP), AL MOVB AL, ret+176(FP) RET // func FieldUint16(s Struct) uint16 -TEXT ·FieldUint16(SB), 0, $0-178 +TEXT ·FieldUint16(SB), $0-178 MOVW s_Uint16+2(FP), AX MOVW AX, ret+176(FP) RET // func FieldInt32(s Struct) int32 -TEXT ·FieldInt32(SB), 0, $0-180 +TEXT ·FieldInt32(SB), $0-180 MOVL s_Int32+4(FP), AX MOVL AX, ret+176(FP) RET // func FieldUint64(s Struct) uint64 -TEXT ·FieldUint64(SB), 0, $0-184 +TEXT ·FieldUint64(SB), $0-184 MOVQ s_Uint64+8(FP), AX MOVQ AX, ret+176(FP) RET // func FieldFloat32(s Struct) float32 -TEXT ·FieldFloat32(SB), 0, $0-180 +TEXT ·FieldFloat32(SB), $0-180 MOVSS s_Float32+16(FP), X0 MOVSS X0, ret+176(FP) RET // func FieldFloat64(s Struct) float64 -TEXT ·FieldFloat64(SB), 0, $0-184 +TEXT ·FieldFloat64(SB), $0-184 MOVSD s_Float64+24(FP), X0 MOVSD X0, ret+176(FP) RET // func FieldStringLen(s Struct) int -TEXT ·FieldStringLen(SB), 0, $0-184 +TEXT ·FieldStringLen(SB), $0-184 MOVQ s_String_len+40(FP), AX MOVQ AX, ret+176(FP) RET // func FieldSliceCap(s Struct) int -TEXT ·FieldSliceCap(SB), 0, $0-184 +TEXT ·FieldSliceCap(SB), $0-184 MOVQ s_Slice_cap+64(FP), AX MOVQ AX, ret+176(FP) RET // func FieldArrayTwoBTwo(s Struct) byte -TEXT ·FieldArrayTwoBTwo(SB), 0, $0-177 +TEXT ·FieldArrayTwoBTwo(SB), $0-177 MOVB s_Array_2_B_2+114(FP), AL MOVB AL, ret+176(FP) RET // func FieldArrayOneC(s Struct) uint16 -TEXT ·FieldArrayOneC(SB), 0, $0-178 +TEXT ·FieldArrayOneC(SB), $0-178 MOVW s_Array_1_C+100(FP), AX MOVW AX, ret+176(FP) RET // func FieldComplex64Imag(s Struct) float32 -TEXT ·FieldComplex64Imag(SB), 0, $0-180 +TEXT ·FieldComplex64Imag(SB), $0-180 MOVSS s_Complex64_imag+156(FP), X0 MOVSS X0, ret+176(FP) RET // func FieldComplex128Real(s Struct) float64 -TEXT ·FieldComplex128Real(SB), 0, $0-184 +TEXT ·FieldComplex128Real(SB), $0-184 MOVSD s_Complex128_real+160(FP), X0 MOVSD X0, ret+176(FP) RET diff --git a/examples/complex/complex.s b/examples/complex/complex.s index c1c18e6f..aaed05c9 100644 --- a/examples/complex/complex.s +++ b/examples/complex/complex.s @@ -3,19 +3,19 @@ #include "textflag.h" // func Real(z complex128) float64 -TEXT ·Real(SB), 0, $0-24 +TEXT ·Real(SB), $0-24 MOVSD z_real(FP), X0 MOVSD X0, ret+16(FP) RET // func Imag(z complex128) float64 -TEXT ·Imag(SB), 0, $0-24 +TEXT ·Imag(SB), $0-24 MOVSD z_imag+8(FP), X0 MOVSD X0, ret+16(FP) RET // func Norm(z complex128) float64 -TEXT ·Norm(SB), 0, $0-24 +TEXT ·Norm(SB), $0-24 MOVSD z_real(FP), X0 MOVSD z_imag+8(FP), X1 MULSD X0, X0 diff --git a/examples/data/data.s b/examples/data/data.s index d722ea5c..8962ddbc 100644 --- a/examples/data/data.s +++ b/examples/data/data.s @@ -13,7 +13,7 @@ DATA bytes<>+39(SB)/1, $0x77 GLOBL bytes<>(SB), RODATA, $40 // func DataAt(i int) byte -TEXT ·DataAt(SB), 0, $0-9 +TEXT ·DataAt(SB), $0-9 MOVQ i(FP), AX LEAQ bytes<>(SB), CX MOVB (CX)(AX*1), AL diff --git a/examples/dot/dot.s b/examples/dot/dot.s index d8d8a6a1..2ff37c65 100644 --- a/examples/dot/dot.s +++ b/examples/dot/dot.s @@ -3,7 +3,7 @@ #include "textflag.h" // func Dot(x []float32, y []float32) float32 -TEXT ·Dot(SB), 0, $0-52 +TEXT ·Dot(SB), $0-52 MOVQ x_base(FP), AX MOVQ y_base+24(FP), CX MOVQ x_len+8(FP), DX diff --git a/examples/fnv1a/fnv1a.s b/examples/fnv1a/fnv1a.s index b466b59e..dacb54d4 100644 --- a/examples/fnv1a/fnv1a.s +++ b/examples/fnv1a/fnv1a.s @@ -3,7 +3,7 @@ #include "textflag.h" // func Hash64(data []byte) uint64 -TEXT ·Hash64(SB), 0, $0-32 +TEXT ·Hash64(SB), $0-32 MOVQ data_base(FP), CX MOVQ data_len+8(FP), BX MOVQ $0xcbf29ce484222325, AX diff --git a/examples/geohash/geohash.s b/examples/geohash/geohash.s index 4cde2293..dc62e25e 100644 --- a/examples/geohash/geohash.s +++ b/examples/geohash/geohash.s @@ -3,7 +3,7 @@ #include "textflag.h" // func EncodeInt(lat float64, lng float64) uint64 -TEXT ·EncodeInt(SB), 0, $0-24 +TEXT ·EncodeInt(SB), $0-24 MOVSD lat(FP), X0 MOVSD lng+8(FP), X1 MULSD reciprocal180<>(SB), X0 diff --git a/examples/returns/returns.s b/examples/returns/returns.s index 1d1c5453..515e013b 100644 --- a/examples/returns/returns.s +++ b/examples/returns/returns.s @@ -3,7 +3,7 @@ #include "textflag.h" // func Interval(start uint64, size uint64) (uint64, uint64) -TEXT ·Interval(SB), 0, $0-32 +TEXT ·Interval(SB), $0-32 MOVQ start(FP), AX MOVQ size+8(FP), CX ADDQ AX, CX @@ -12,7 +12,7 @@ TEXT ·Interval(SB), 0, $0-32 RET // func Butterfly(x0 float64, x1 float64) (y0 float64, y1 float64) -TEXT ·Butterfly(SB), 0, $0-32 +TEXT ·Butterfly(SB), $0-32 MOVSD x0(FP), X0 MOVSD x1+8(FP), X1 MOVSD X0, X2 @@ -24,7 +24,7 @@ TEXT ·Butterfly(SB), 0, $0-32 RET // func Septuple(byte) [7]byte -TEXT ·Septuple(SB), 0, $0-15 +TEXT ·Septuple(SB), $0-15 MOVB arg(FP), AL MOVB AL, ret_0+8(FP) MOVB AL, ret_1+9(FP) @@ -36,7 +36,7 @@ TEXT ·Septuple(SB), 0, $0-15 RET // func CriticalLine(t float64) complex128 -TEXT ·CriticalLine(SB), 0, $0-24 +TEXT ·CriticalLine(SB), $0-24 MOVSD t(FP), X0 MOVSD half<>(SB), X1 MOVSD X1, ret_real+8(FP) @@ -47,7 +47,7 @@ DATA half<>(SB)/8, $(0.5) GLOBL half<>(SB), RODATA, $8 // func NewStruct(w uint16, p [2]float64, q uint64) Struct -TEXT ·NewStruct(SB), 0, $0-64 +TEXT ·NewStruct(SB), $0-64 MOVW w(FP), AX MOVSD p_0+8(FP), X0 MOVSD p_1+16(FP), X1 diff --git a/examples/sha1/sha1.s b/examples/sha1/sha1.s index d5e3752c..9f564867 100644 --- a/examples/sha1/sha1.s +++ b/examples/sha1/sha1.s @@ -3,7 +3,7 @@ #include "textflag.h" // func block(h *[5]uint32, m []byte) -TEXT ·block(SB), 0, $64-32 +TEXT ·block(SB), $64-32 MOVQ h(FP), AX MOVQ m_base+8(FP), CX MOVL (AX), DX diff --git a/examples/stadtx/stadtx.s b/examples/stadtx/stadtx.s index 54e45268..0d91e3f7 100644 --- a/examples/stadtx/stadtx.s +++ b/examples/stadtx/stadtx.s @@ -3,7 +3,7 @@ #include "textflag.h" // func Hash(state *State, key []byte) uint64 -TEXT ·Hash(SB), 0, $0-40 +TEXT ·Hash(SB), $0-40 MOVQ state(FP), AX MOVQ key_base+8(FP), CX MOVQ key_len+16(FP), DX diff --git a/examples/sum/sum.s b/examples/sum/sum.s index 24d042ef..0282faf7 100644 --- a/examples/sum/sum.s +++ b/examples/sum/sum.s @@ -3,7 +3,7 @@ #include "textflag.h" // func Sum(xs []uint64) uint64 -TEXT ·Sum(SB), 0, $0-32 +TEXT ·Sum(SB), $0-32 MOVQ xs_base(FP), AX MOVQ xs_len+8(FP), CX XORQ DX, DX diff --git a/printer/goasm.go b/printer/goasm.go index 4104e305..adc7217c 100644 --- a/printer/goasm.go +++ b/printer/goasm.go @@ -49,7 +49,26 @@ func (p *goasm) include(path string) { func (p *goasm) function(f *avo.Function) { p.NL() p.Comment(f.Stub()) - p.Printf("TEXT %s%s(SB), 0, %s\n", dot, f.Name, textsize(f)) + + // Reference: https://github.com/golang/go/blob/b115207baf6c2decc3820ada4574ef4e5ad940ec/src/cmd/internal/obj/util.go#L166-L176 + // + // if p.As == ATEXT { + // // If there are attributes, print them. Otherwise, skip the comma. + // // In short, print one of these two: + // // TEXT foo(SB), DUPOK|NOSPLIT, $0 + // // TEXT foo(SB), $0 + // s := p.From.Sym.Attribute.TextAttrString() + // if s != "" { + // fmt.Fprintf(&buf, "%s%s", sep, s) + // sep = ", " + // } + // } + // + p.Printf("TEXT %s%s(SB)", dot, f.Name) + if f.Attributes != 0 { + p.Printf(", %s", f.Attributes.Asm()) + } + p.Printf(", %s\n", textsize(f)) for _, node := range f.Nodes { switch n := node.(type) { @@ -73,8 +92,7 @@ func (p *goasm) global(g *avo.Global) { a := operand.NewDataAddr(g.Symbol, d.Offset) p.Printf("DATA %s/%d, %s\n", a.Asm(), d.Value.Bytes(), d.Value.Asm()) } - // TODO(mbm): replace hardcoded RODATA with an attributes list - p.Printf("GLOBL %s(SB), RODATA, $%d\n", g.Symbol, g.Size) + p.Printf("GLOBL %s(SB), %s, $%d\n", g.Symbol, g.Attributes.Asm(), g.Size) } func textsize(f *avo.Function) string { diff --git a/printer/goasm_test.go b/printer/goasm_test.go index 0ab7d392..6dd334a6 100644 --- a/printer/goasm_test.go +++ b/printer/goasm_test.go @@ -3,6 +3,7 @@ package printer_test import ( "testing" + "github.com/mmcloughlin/avo" "github.com/mmcloughlin/avo/build" "github.com/mmcloughlin/avo/printer" "github.com/mmcloughlin/avo/reg" @@ -24,7 +25,7 @@ func TestBasic(t *testing.T) { "#include \"textflag.h\"", "", "// func add(x uint64, y uint64) uint64", - "TEXT ·add(SB), 0, $0-24", + "TEXT ·add(SB), $0-24", "\tMOVQ\tx(FP), AX", "\tMOVQ\ty+8(FP), R9", "\tADDQ\tAX, R9", @@ -34,7 +35,7 @@ func TestBasic(t *testing.T) { }) } -func TestTextSize(t *testing.T) { +func TestTextDecl(t *testing.T) { ctx := build.NewContext() ctx.Function("noargs") @@ -46,17 +47,26 @@ func TestTextSize(t *testing.T) { ctx.SignatureExpr("func(x, y uint64) uint64") ctx.RET() + ctx.Function("withattr") + ctx.SignatureExpr("func()") + ctx.Attributes(avo.NOSPLIT | avo.TLSBSS) + ctx.RET() + AssertPrintsLines(t, ctx, printer.NewGoAsm, []string{ "// Code generated by avo. DO NOT EDIT.", "", "#include \"textflag.h\"", "", "// func noargs()", - "TEXT ·noargs(SB), 0, $16", // expect only the frame size + "TEXT ·noargs(SB), $16", // expect only the frame size "\tRET", "", "// func withargs(x uint64, y uint64) uint64", - "TEXT ·withargs(SB), 0, $0-24", // expect both frame size and argument size + "TEXT ·withargs(SB), $0-24", // expect both frame size and argument size + "\tRET", + "", + "// func withattr()", + "TEXT ·withattr(SB), NOSPLIT|TLSBSS, $0", // expect to see attributes "\tRET", "", }) diff --git a/tests/cast/cast.s b/tests/cast/cast.s index 74fb0253..57d644d5 100644 --- a/tests/cast/cast.s +++ b/tests/cast/cast.s @@ -3,7 +3,7 @@ #include "textflag.h" // func Split(x uint64) (q uint64, l uint32, w uint16, b uint8) -TEXT ·Split(SB), 0, $0-23 +TEXT ·Split(SB), $0-23 MOVQ x(FP), AX MOVQ AX, q+8(FP) MOVL AX, l+16(FP)