-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathbuilder.go
88 lines (73 loc) · 1.64 KB
/
builder.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package golangasm
import (
"fmt"
"github.com/twitchyliquid64/golang-asm/asm/arch"
"github.com/twitchyliquid64/golang-asm/obj"
"github.com/twitchyliquid64/golang-asm/objabi"
)
// Builder allows you to assemble a series of instructions.
type Builder struct {
ctxt *obj.Link
arch *arch.Arch
first *obj.Prog
last *obj.Prog
// bulk allocator.
block *[]obj.Prog
used int
}
// Root returns the first instruction.
func (b *Builder) Root() *obj.Prog {
return b.first
}
// NewProg returns a new instruction structure.
func (b *Builder) NewProg() *obj.Prog {
return b.progAlloc()
}
func (b *Builder) progAlloc() *obj.Prog {
var p *obj.Prog
if b.used >= len(*b.block) {
p = b.ctxt.NewProg()
} else {
p = &(*b.block)[b.used]
b.used++
}
p.Ctxt = b.ctxt
return p
}
// AddInstruction adds an instruction to the list of instructions
// to be assembled.
func (b *Builder) AddInstruction(p *obj.Prog) {
if b.first == nil {
b.first = p
b.last = p
} else {
b.last.Link = p
b.last = p
}
}
// Assemble generates the machine code from the given instructions.
func (b *Builder) Assemble() []byte {
s := &obj.LSym{
Func: &obj.FuncInfo{
Text: b.first,
},
}
b.arch.Assemble(b.ctxt, s, b.progAlloc)
return s.P
}
// NewBuilder constructs an assembler for the given architecture.
func NewBuilder(archStr string, cacheSize int) (*Builder, error) {
a := arch.Set(archStr)
ctxt := obj.Linknew(a.LinkArch)
ctxt.Headtype = objabi.Hlinux
ctxt.DiagFunc = func(in string, args ...interface{}) {
fmt.Printf(in+"\n", args...)
}
a.Init(ctxt)
block := make([]obj.Prog, cacheSize)
return &Builder{
ctxt: ctxt,
arch: a,
block: &block,
}, nil
}