github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/assembler/assembler.go (about) 1 // Copyright 2021 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package assembler 6 7 import ( 8 "fmt" 9 10 "github.com/go-asm/go/cmd/asm/arch" 11 "github.com/go-asm/go/cmd/obj" 12 "github.com/go-asm/go/cmd/objabi" 13 ) 14 15 // Builder allows you to assemble a series of instructions. 16 type Builder struct { 17 ctxt *obj.Link 18 arch *arch.Arch 19 20 first *obj.Prog 21 last *obj.Prog 22 23 // bulk allocator. 24 block *[]obj.Prog 25 used int 26 } 27 28 // Root returns the first instruction. 29 func (b *Builder) Root() *obj.Prog { 30 return b.first 31 } 32 33 // NewProg returns a new instruction structure. 34 func (b *Builder) NewProg() *obj.Prog { 35 return b.progAlloc() 36 } 37 38 func (b *Builder) progAlloc() *obj.Prog { 39 var p *obj.Prog 40 41 if b.used >= len(*b.block) { 42 p = b.ctxt.NewProg() 43 } else { 44 p = &(*b.block)[b.used] 45 b.used++ 46 } 47 48 p.Ctxt = b.ctxt 49 return p 50 } 51 52 // AddInstruction adds an instruction to the list of instructions 53 // to be assembled. 54 func (b *Builder) AddInstruction(p *obj.Prog) { 55 if b.first == nil { 56 b.first = p 57 b.last = p 58 } else { 59 b.last.Link = p 60 b.last = p 61 } 62 } 63 64 // Assemble generates the machine code from the given instructions. 65 func (b *Builder) Assemble() []byte { 66 s := &obj.LSym{} 67 s.Extra = new(interface{}) 68 *s.Extra = &obj.FuncInfo{ 69 Text: b.first, 70 } 71 b.arch.Assemble(b.ctxt, s, b.progAlloc) 72 73 return s.P 74 } 75 76 // NewBuilder constructs an assembler for the given architecture. 77 func NewBuilder(archStr string, cacheSize int) (*Builder, error) { 78 a := arch.Set(archStr, false) 79 ctxt := obj.Linknew(a.LinkArch) 80 ctxt.Headtype = objabi.Hlinux 81 ctxt.DiagFunc = func(in string, args ...interface{}) { 82 fmt.Printf(in+"\n", args...) 83 } 84 a.Init(ctxt) 85 86 block := make([]obj.Prog, cacheSize) 87 88 b := &Builder{ 89 ctxt: ctxt, 90 arch: a, 91 block: &block, 92 } 93 94 return b, nil 95 }