Commit 4ca2fc4d authored by Russ Cox's avatar Russ Cox

[dev.cc] cmd/new5a etc, cmd/internal/asm: edit to produce working Go code

These assemblers produce byte-for-byte identical output
to the ones written in C.

They are primarily a proof that cmd/internal/obj can be used
standalone to produce working object files. (The use via objwriter
starts by deserializing an already-constructed internal representation,
so objwriter does not exercise the code in cmd/internal/obj that
creates such a representation from scratch.)

Change-Id: I1793d8d010046cfb9d8b4d2d4469e7f47a3d3ac7
Reviewed-on: https://go-review.googlesource.com/3143Reviewed-by: 's avatarRob Pike <r@golang.org>
Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
parent 9e2f8fdb
...@@ -26,14 +26,12 @@ misc/cgo/life/run.out ...@@ -26,14 +26,12 @@ misc/cgo/life/run.out
misc/cgo/stdio/run.out misc/cgo/stdio/run.out
misc/cgo/testso/main misc/cgo/testso/main
misc/dashboard/builder/builder misc/dashboard/builder/builder
src/cmd/?a/y.output
src/liblink/anames?.c src/liblink/anames?.c
src/cmd/cc/y.output src/cmd/*/y.output
src/cmd/cgo/zdefaultcc.go src/cmd/cgo/zdefaultcc.go
src/cmd/dist/dist.dSYM src/cmd/dist/dist.dSYM
src/cmd/gc/mkbuiltin1 src/cmd/gc/mkbuiltin1
src/cmd/gc/opnames.h src/cmd/gc/opnames.h
src/cmd/gc/y.output
src/cmd/go/zdefaultcc.go src/cmd/go/zdefaultcc.go
src/cmd/internal/obj/zbootstrap.go src/cmd/internal/obj/zbootstrap.go
src/go/doc/headscan src/go/doc/headscan
......
...@@ -396,6 +396,10 @@ var goTools = map[string]targetDir{ ...@@ -396,6 +396,10 @@ var goTools = map[string]targetDir{
"cmd/cgo": toTool, "cmd/cgo": toTool,
"cmd/fix": toTool, "cmd/fix": toTool,
"cmd/link": toTool, "cmd/link": toTool,
"cmd/new5a": toTool,
"cmd/new6a": toTool,
"cmd/new8a": toTool,
"cmd/new9a": toTool,
"cmd/nm": toTool, "cmd/nm": toTool,
"cmd/objdump": toTool, "cmd/objdump": toTool,
"cmd/objwriter": toTool, "cmd/objwriter": toTool,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -28,162 +28,66 @@ ...@@ -28,162 +28,66 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
//go:generate go tool yacc a.y
package main package main
const ( import (
Plan9 = 1 << 0 "cmd/internal/asm"
Unix = 1 << 1 "cmd/internal/obj"
Windows = 1 << 2 "cmd/internal/obj/arm"
) )
func systemtype(sys int) int { var (
return sys & Windows yyerror = asm.Yyerror
nullgen obj.Addr
return sys & Plan9 stmtline int32
} )
func Lconv(fp *obj.Fmt) int {
return obj.Linklinefmt(Ctxt, fp)
}
func dodef(p string) {
if nDlist%8 == 0 {
Dlist = asm.Allocn(Dlist, nDlist*sizeof(string), 8*sizeof(string)).(*string)
}
Dlist[nDlist] = p
nDlist++
}
func usage() {
fmt.Printf("usage: %ca [options] file.c...\n", Thechar)
main.Flagprint(1)
asm.Errorexit()
}
func main(argc int, argv [XXX]string) {
var p string
Thechar = '5'
thestring = "arm"
Ctxt = obj.Linknew(&arm.Linkarm)
Ctxt.Diag = asm.Yyerror
Ctxt.Bso = &Bstdout
Ctxt.Enforce_data_order = 1
obj.Binit(&Bstdout, 1, main.OWRITE)
arm.Listinit5()
obj.Fmtinstall('L', Lconv)
// Allow GOARCH=thestring or GOARCH=thestringsuffix,
// but not other values.
p = Getgoarch()
if !strings.HasPrefix(p, thestring) { const Always = 14
log.Fatalf("cannot use %cc with GOARCH=%s", Thechar, p)
}
asm.Ensuresymb(NSYMB) func main() {
Debug = [256]int{}
cinit() cinit()
Outfile = ""
asm.Setinclude(".")
main.Flagfn1("D", "name[=value]: add #define", dodef) asm.LSCONST = LSCONST
main.Flagfn1("I", "dir: add dir to include path", asm.Setinclude) asm.LCONST = LCONST
main.Flagcount("S", "print assembly and machine code", &Debug['S']) asm.LFCONST = LFCONST
main.Flagcount("m", "debug preprocessor macros", &Debug['m']) asm.LNAME = LNAME
main.Flagstr("o", "file: set output file", &Outfile) asm.LVAR = LVAR
main.Flagstr("trimpath", "prefix: remove prefix from recorded source file paths", &Ctxt.Trimpath) asm.LLAB = LLAB
main.Flagparse(&argc, (**string)(&argv), usage) asm.Lexinit = lexinit
Ctxt.Debugasm = int32(Debug['S']) asm.Cclean = cclean
asm.Yyparse = yyparse
if argc < 1 { asm.Thechar = '5'
usage() asm.Thestring = "arm"
} asm.Thelinkarch = &arm.Linkarm
if argc > 1 {
fmt.Printf("can't assemble multiple files\n")
asm.Errorexit()
}
if assemble(argv[0]) != 0 { asm.Main()
asm.Errorexit()
}
obj.Bflush(&Bstdout)
if Nerrors > 0 {
asm.Errorexit()
}
main.Exits("")
} }
func assemble(file string) int { type yy struct{}
var ofile string
var p string
var i int
var of int
ofile = asm.Alloc(int32(len(file)) + 3).(string) // +3 for .x\0 (x=thechar) func (yy) Lex(v *yySymType) int {
ofile = file var av asm.Yylval
p = main.Utfrrune(ofile, '/') tok := asm.Yylex(&av)
if p != "" { v.sym = av.Sym
Include[0] = ofile v.lval = int32(av.Lval)
p = "" v.sval = av.Sval
p = p[1:] v.dval = av.Dval
} else { return tok
}
p = ofile
}
if Outfile == "" {
Outfile = p
if Outfile != "" {
p = main.Utfrrune(Outfile, '.')
if p != "" {
if p[1] == 's' && p[2] == 0 {
p = ""
}
}
p = main.Utfrune(Outfile, 0)
p[0] = '.'
p[1] = byte(Thechar)
p[2] = 0
} else {
Outfile = "/dev/null"
}
}
of = main.Create(Outfile, main.OWRITE, 0664)
if of < 0 {
asm.Yyerror("%ca: cannot create %s", Thechar, Outfile)
asm.Errorexit()
}
obj.Binit(&obuf, of, main.OWRITE)
fmt.Fprintf(&obuf, "go object %s %s %s\n", main.Getgoos(), main.Getgoarch(), main.Getgoversion())
fmt.Fprintf(&obuf, "!\n")
for pass = 1; pass <= 2; pass++ { func (yy) Error(msg string) {
asm.Pinit(file) asm.Yyerror("%s", msg)
for i = 0; i < nDlist; i++ { }
asm.Dodefine(Dlist[i])
}
yyparse()
cclean()
if Nerrors != 0 {
return Nerrors
}
}
obj.Writeobj(Ctxt, &obuf) func yyparse() {
obj.Bflush(&obuf) yyParse(yy{})
return 0
} }
var itab = []struct { var lexinit = []asm.Lextab{
name string
type_ uint16
value uint16
}{
{"SP", LSP, arm.D_AUTO}, {"SP", LSP, arm.D_AUTO},
{"SB", LSB, arm.D_EXTERN}, {"SB", LSB, arm.D_EXTERN},
{"FP", LFP, arm.D_PARAM}, {"FP", LFP, arm.D_PARAM},
...@@ -394,39 +298,17 @@ var itab = []struct { ...@@ -394,39 +298,17 @@ var itab = []struct {
} }
func cinit() { func cinit() {
var s *Sym nullgen.Type_ = arm.D_NONE
var i int nullgen.Name = arm.D_NONE
nullgen.Reg = arm.NREG
Nullgen.Type_ = arm.D_NONE
Nullgen.Name = arm.D_NONE
Nullgen.Reg = arm.NREG
Nerrors = 0
Iostack = nil
Iofree = nil
Peekc = IGN
nhunk = 0
for i = 0; i < NHASH; i++ {
Hash[i] = nil
}
for i = 0; itab[i].name != ""; i++ {
s = asm.Slookup(itab[i].name)
s.Type_ = itab[i].type_
s.Value = int32(itab[i].value)
}
}
func Syminit(s *Sym) {
s.Type_ = LNAME
s.Value = 0
} }
func isreg(g *obj.Addr) int { func isreg(g *obj.Addr) bool {
return 1 return true
} }
func cclean() { func cclean() {
outcode(arm.AEND, Always, &Nullgen, arm.NREG, &Nullgen) outcode(arm.AEND, Always, &nullgen, arm.NREG, &nullgen)
} }
var bcode = []int{ var bcode = []int{
...@@ -450,42 +332,41 @@ var bcode = []int{ ...@@ -450,42 +332,41 @@ var bcode = []int{
var lastpc *obj.Prog var lastpc *obj.Prog
func outcode(a int, scond int, g1 *obj.Addr, reg int, g2 *obj.Addr) { func outcode(a, scond int32, g1 *obj.Addr, reg int32, g2 *obj.Addr) {
var p *obj.Prog var p *obj.Prog
var pl *obj.Plist var pl *obj.Plist
/* hack to make B.NE etc. work: turn it into the corresponding conditional */ /* hack to make B.NE etc. work: turn it into the corresponding conditional */
if a == arm.AB { if a == arm.AB {
a = int32(bcode[scond&0xf])
a = bcode[scond&0xf] scond = (scond &^ 0xf) | Always
scond = scond&^0xf | Always
} }
if pass == 1 { if asm.Pass == 1 {
goto out goto out
} }
p = new(obj.Prog) p = new(obj.Prog)
*p = obj.Prog{} *p = obj.Prog{}
p.Ctxt = asm.Ctxt
p.As = int16(a) p.As = int16(a)
p.Lineno = stmtline p.Lineno = stmtline
p.Scond = uint8(scond) p.Scond = uint8(scond)
p.From = *g1 p.From = *g1
p.Reg = uint8(reg) p.Reg = uint8(reg)
p.To = *g2 p.To = *g2
p.Pc = int64(Pc) p.Pc = int64(asm.PC)
if lastpc == nil { if lastpc == nil {
pl = obj.Linknewplist(Ctxt) pl = obj.Linknewplist(asm.Ctxt)
pl.Firstpc = p pl.Firstpc = p
} else { } else {
lastpc.Link = p lastpc.Link = p
} }
lastpc = p lastpc = p
out: out:
if a != arm.AGLOBL && a != arm.ADATA { if a != arm.AGLOBL && a != arm.ADATA {
Pc++ asm.PC++
} }
} }
This diff is collapsed.
This diff is collapsed.
...@@ -28,171 +28,67 @@ ...@@ -28,171 +28,67 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
//go:generate go tool yacc a.y
package main package main
const ( import (
Plan9 = 1 << 0 "cmd/internal/asm"
Unix = 1 << 1 "cmd/internal/obj"
Windows = 1 << 2 "cmd/internal/obj/x86"
) )
func systemtype(sys int) int { var (
return sys & Windows yyerror = asm.Yyerror
nullgen obj.Addr
return sys & Plan9 stmtline int32
} )
func pathchar() int {
return '/'
}
func Lconv(fp *obj.Fmt) int { func main() {
return obj.Linklinefmt(ctxt, fp) cinit()
}
func dodef(p string) { asm.LSCONST = LSCONST
if nDlist%8 == 0 { asm.LCONST = LCONST
Dlist = allocn(Dlist, nDlist*sizeof(string), 8*sizeof(string)).(*string) asm.LFCONST = LFCONST
asm.LNAME = LNAME
asm.LVAR = LVAR
asm.LLAB = LLAB
asm.Thechar = '6'
asm.Thestring = "amd64"
asm.Thelinkarch = &x86.Linkamd64
asm.Arches = map[string]*obj.LinkArch{
"amd64p32": &x86.Linkamd64p32,
} }
Dlist[nDlist] = p
nDlist++
}
var thelinkarch *obj.LinkArch = &x86.Linkamd64 asm.Lexinit = lexinit
asm.Cclean = cclean
asm.Yyparse = yyparse
func usage() { asm.Main()
fmt.Printf("usage: %ca [options] file.c...\n", thechar)
main.Flagprint(1)
errorexit()
} }
func main(argc int, argv [XXX]string) { type yy struct{}
var p string
thechar = '6'
thestring = "amd64"
// Allow GOARCH=thestring or GOARCH=thestringsuffix,
// but not other values.
p = Getgoarch()
if !strings.HasPrefix(p, thestring) {
log.Fatalf("cannot use %cc with GOARCH=%s", thechar, p)
}
if p == "amd64p32" {
thelinkarch = &x86.Linkamd64p32
}
ctxt = obj.Linknew(thelinkarch)
ctxt.Diag = yyerror
ctxt.Bso = &bstdout
ctxt.Enforce_data_order = 1
obj.Binit(&bstdout, 1, main.OWRITE)
x86.Listinit6()
obj.Fmtinstall('L', Lconv)
ensuresymb(NSYMB)
debug = [256]int{}
cinit()
outfile = ""
setinclude(".")
main.Flagfn1("D", "name[=value]: add #define", dodef) func (yy) Lex(v *yySymType) int {
main.Flagfn1("I", "dir: add dir to include path", setinclude) var av asm.Yylval
main.Flagcount("S", "print assembly and machine code", &debug['S']) tok := asm.Yylex(&av)
main.Flagcount("m", "debug preprocessor macros", &debug['m']) v.sym = av.Sym
main.Flagstr("o", "file: set output file", &outfile) v.lval = av.Lval
main.Flagstr("trimpath", "prefix: remove prefix from recorded source file paths", &ctxt.Trimpath) v.sval = av.Sval
v.dval = av.Dval
main.Flagparse(&argc, (**string)(&argv), usage) return tok
ctxt.Debugasm = int32(debug['S'])
if argc < 1 {
usage()
}
if argc > 1 {
fmt.Printf("can't assemble multiple files\n")
errorexit()
}
if assemble(argv[0]) != 0 {
errorexit()
}
obj.Bflush(&bstdout)
if nerrors > 0 {
errorexit()
}
main.Exits("")
} }
func assemble(file string) int { func (yy) Error(msg string) {
var ofile string asm.Yyerror("%s", msg)
var p string }
var i int
var of int
ofile = alloc(int32(len(file)) + 3).(string) // +3 for .x\0 (x=thechar)
ofile = file
p = main.Utfrrune(ofile, uint(pathchar()))
if p != "" {
include[0] = ofile
p = ""
p = p[1:]
} else {
p = ofile
}
if outfile == "" {
outfile = p
if outfile != "" {
p = main.Utfrrune(outfile, '.')
if p != "" {
if p[1] == 's' && p[2] == 0 {
p = ""
}
}
p = main.Utfrune(outfile, 0)
p[0] = '.'
p[1] = byte(thechar)
p[2] = 0
} else {
outfile = "/dev/null"
}
}
of = main.Create(outfile, main.OWRITE, 0664)
if of < 0 {
yyerror("%ca: cannot create %s", thechar, outfile)
errorexit()
}
obj.Binit(&obuf, of, main.OWRITE)
fmt.Fprintf(&obuf, "go object %s %s %s\n", main.Getgoos(), main.Getgoarch(), main.Getgoversion())
fmt.Fprintf(&obuf, "!\n")
for pass = 1; pass <= 2; pass++ {
pinit(file)
for i = 0; i < nDlist; i++ {
dodefine(Dlist[i])
}
yyparse()
cclean()
if nerrors != 0 {
return nerrors
}
}
obj.Writeobj(ctxt, &obuf) func yyparse() {
obj.Bflush(&obuf) yyParse(yy{})
return 0
} }
var itab = []struct { var lexinit = []asm.Lextab{
name string
type_ uint16
value uint16
}{
{"SP", LSP, x86.D_AUTO}, {"SP", LSP, x86.D_AUTO},
{"SB", LSB, x86.D_EXTERN}, {"SB", LSB, x86.D_EXTERN},
{"FP", LFP, x86.D_PARAM}, {"FP", LFP, x86.D_PARAM},
...@@ -1019,31 +915,11 @@ var itab = []struct { ...@@ -1019,31 +915,11 @@ var itab = []struct {
} }
func cinit() { func cinit() {
var s *Sym
var i int
nullgen.Type_ = x86.D_NONE nullgen.Type_ = x86.D_NONE
nullgen.Index = x86.D_NONE nullgen.Index = x86.D_NONE
nerrors = 0
iostack = nil
iofree = nil
peekc = IGN
nhunk = 0
for i = 0; i < NHASH; i++ {
hash[i] = nil
}
for i = 0; itab[i].name != ""; i++ {
s = slookup(itab[i].name)
if s.type_ != LNAME {
yyerror("double initialization %s", itab[i].name)
}
s.type_ = itab[i].type_
s.value = int64(itab[i].value)
}
} }
func checkscale(scale int) { func checkscale(scale int8) {
switch scale { switch scale {
case 1, case 1,
2, 2,
...@@ -1055,11 +931,6 @@ func checkscale(scale int) { ...@@ -1055,11 +931,6 @@ func checkscale(scale int) {
yyerror("scale must be 1248: %d", scale) yyerror("scale must be 1248: %d", scale)
} }
func syminit(s *Sym) {
s.type_ = LNAME
s.value = 0
}
func cclean() { func cclean() {
var g2 Addr2 var g2 Addr2
...@@ -1070,24 +941,30 @@ func cclean() { ...@@ -1070,24 +941,30 @@ func cclean() {
var lastpc *obj.Prog var lastpc *obj.Prog
type Addr2 struct {
from obj.Addr
to obj.Addr
}
func outcode(a int, g2 *Addr2) { func outcode(a int, g2 *Addr2) {
var p *obj.Prog var p *obj.Prog
var pl *obj.Plist var pl *obj.Plist
if pass == 1 { if asm.Pass == 1 {
goto out goto out
} }
p = new(obj.Prog) p = new(obj.Prog)
*p = obj.Prog{} *p = obj.Prog{}
p.Ctxt = asm.Ctxt
p.As = int16(a) p.As = int16(a)
p.Lineno = stmtline p.Lineno = stmtline
p.From = g2.from p.From = g2.from
p.To = g2.to p.To = g2.to
p.Pc = int64(pc) p.Pc = int64(asm.PC)
if lastpc == nil { if lastpc == nil {
pl = obj.Linknewplist(ctxt) pl = obj.Linknewplist(asm.Ctxt)
pl.Firstpc = p pl.Firstpc = p
} else { } else {
...@@ -1097,6 +974,6 @@ func outcode(a int, g2 *Addr2) { ...@@ -1097,6 +974,6 @@ func outcode(a int, g2 *Addr2) {
out: out:
if a != x86.AGLOBL && a != x86.ADATA { if a != x86.AGLOBL && a != x86.ADATA {
pc++ asm.PC++
} }
} }
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment