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
misc/cgo/stdio/run.out
misc/cgo/testso/main
misc/dashboard/builder/builder
src/cmd/?a/y.output
src/liblink/anames?.c
src/cmd/cc/y.output
src/cmd/*/y.output
src/cmd/cgo/zdefaultcc.go
src/cmd/dist/dist.dSYM
src/cmd/gc/mkbuiltin1
src/cmd/gc/opnames.h
src/cmd/gc/y.output
src/cmd/go/zdefaultcc.go
src/cmd/internal/obj/zbootstrap.go
src/go/doc/headscan
......
......@@ -396,6 +396,10 @@ var goTools = map[string]targetDir{
"cmd/cgo": toTool,
"cmd/fix": toTool,
"cmd/link": toTool,
"cmd/new5a": toTool,
"cmd/new6a": toTool,
"cmd/new8a": toTool,
"cmd/new9a": toTool,
"cmd/nm": toTool,
"cmd/objdump": toTool,
"cmd/objwriter": toTool,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -28,162 +28,66 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//go:generate go tool yacc a.y
package main
const (
Plan9 = 1 << 0
Unix = 1 << 1
Windows = 1 << 2
import (
"cmd/internal/asm"
"cmd/internal/obj"
"cmd/internal/obj/arm"
)
func systemtype(sys int) int {
return sys & Windows
return sys & Plan9
}
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()
var (
yyerror = asm.Yyerror
nullgen obj.Addr
stmtline int32
)
if !strings.HasPrefix(p, thestring) {
log.Fatalf("cannot use %cc with GOARCH=%s", Thechar, p)
}
const Always = 14
asm.Ensuresymb(NSYMB)
Debug = [256]int{}
func main() {
cinit()
Outfile = ""
asm.Setinclude(".")
main.Flagfn1("D", "name[=value]: add #define", dodef)
main.Flagfn1("I", "dir: add dir to include path", asm.Setinclude)
main.Flagcount("S", "print assembly and machine code", &Debug['S'])
main.Flagcount("m", "debug preprocessor macros", &Debug['m'])
main.Flagstr("o", "file: set output file", &Outfile)
main.Flagstr("trimpath", "prefix: remove prefix from recorded source file paths", &Ctxt.Trimpath)
asm.LSCONST = LSCONST
asm.LCONST = LCONST
asm.LFCONST = LFCONST
asm.LNAME = LNAME
asm.LVAR = LVAR
asm.LLAB = LLAB
main.Flagparse(&argc, (**string)(&argv), usage)
Ctxt.Debugasm = int32(Debug['S'])
asm.Lexinit = lexinit
asm.Cclean = cclean
asm.Yyparse = yyparse
if argc < 1 {
usage()
}
if argc > 1 {
fmt.Printf("can't assemble multiple files\n")
asm.Errorexit()
}
asm.Thechar = '5'
asm.Thestring = "arm"
asm.Thelinkarch = &arm.Linkarm
if assemble(argv[0]) != 0 {
asm.Errorexit()
}
obj.Bflush(&Bstdout)
if Nerrors > 0 {
asm.Errorexit()
}
main.Exits("")
asm.Main()
}
func assemble(file string) int {
var ofile string
var p string
var i int
var of int
type yy struct{}
ofile = asm.Alloc(int32(len(file)) + 3).(string) // +3 for .x\0 (x=thechar)
ofile = file
p = main.Utfrrune(ofile, '/')
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 {
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")
func (yy) Lex(v *yySymType) int {
var av asm.Yylval
tok := asm.Yylex(&av)
v.sym = av.Sym
v.lval = int32(av.Lval)
v.sval = av.Sval
v.dval = av.Dval
return tok
}
for pass = 1; pass <= 2; pass++ {
asm.Pinit(file)
for i = 0; i < nDlist; i++ {
asm.Dodefine(Dlist[i])
}
yyparse()
cclean()
if Nerrors != 0 {
return Nerrors
}
}
func (yy) Error(msg string) {
asm.Yyerror("%s", msg)
}
obj.Writeobj(Ctxt, &obuf)
obj.Bflush(&obuf)
return 0
func yyparse() {
yyParse(yy{})
}
var itab = []struct {
name string
type_ uint16
value uint16
}{
var lexinit = []asm.Lextab{
{"SP", LSP, arm.D_AUTO},
{"SB", LSB, arm.D_EXTERN},
{"FP", LFP, arm.D_PARAM},
......@@ -394,39 +298,17 @@ var itab = []struct {
}
func cinit() {
var s *Sym
var i int
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
nullgen.Type_ = arm.D_NONE
nullgen.Name = arm.D_NONE
nullgen.Reg = arm.NREG
}
func isreg(g *obj.Addr) int {
return 1
func isreg(g *obj.Addr) bool {
return true
}
func cclean() {
outcode(arm.AEND, Always, &Nullgen, arm.NREG, &Nullgen)
outcode(arm.AEND, Always, &nullgen, arm.NREG, &nullgen)
}
var bcode = []int{
......@@ -450,42 +332,41 @@ var bcode = []int{
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 pl *obj.Plist
/* hack to make B.NE etc. work: turn it into the corresponding conditional */
if a == arm.AB {
a = bcode[scond&0xf]
scond = scond&^0xf | Always
a = int32(bcode[scond&0xf])
scond = (scond &^ 0xf) | Always
}
if pass == 1 {
if asm.Pass == 1 {
goto out
}
p = new(obj.Prog)
*p = obj.Prog{}
p.Ctxt = asm.Ctxt
p.As = int16(a)
p.Lineno = stmtline
p.Scond = uint8(scond)
p.From = *g1
p.Reg = uint8(reg)
p.To = *g2
p.Pc = int64(Pc)
p.Pc = int64(asm.PC)
if lastpc == nil {
pl = obj.Linknewplist(Ctxt)
pl = obj.Linknewplist(asm.Ctxt)
pl.Firstpc = p
} else {
lastpc.Link = p
}
lastpc = p
out:
if a != arm.AGLOBL && a != arm.ADATA {
Pc++
asm.PC++
}
}
This diff is collapsed.
This diff is collapsed.
......@@ -28,171 +28,67 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//go:generate go tool yacc a.y
package main
const (
Plan9 = 1 << 0
Unix = 1 << 1
Windows = 1 << 2
import (
"cmd/internal/asm"
"cmd/internal/obj"
"cmd/internal/obj/x86"
)
func systemtype(sys int) int {
return sys & Windows
return sys & Plan9
}
func pathchar() int {
return '/'
}
var (
yyerror = asm.Yyerror
nullgen obj.Addr
stmtline int32
)
func Lconv(fp *obj.Fmt) int {
return obj.Linklinefmt(ctxt, fp)
}
func main() {
cinit()
func dodef(p string) {
if nDlist%8 == 0 {
Dlist = allocn(Dlist, nDlist*sizeof(string), 8*sizeof(string)).(*string)
asm.LSCONST = LSCONST
asm.LCONST = LCONST
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() {
fmt.Printf("usage: %ca [options] file.c...\n", thechar)
main.Flagprint(1)
errorexit()
asm.Main()
}
func main(argc int, argv [XXX]string) {
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(".")
type yy struct{}
main.Flagfn1("D", "name[=value]: add #define", dodef)
main.Flagfn1("I", "dir: add dir to include path", setinclude)
main.Flagcount("S", "print assembly and machine code", &debug['S'])
main.Flagcount("m", "debug preprocessor macros", &debug['m'])
main.Flagstr("o", "file: set output file", &outfile)
main.Flagstr("trimpath", "prefix: remove prefix from recorded source file paths", &ctxt.Trimpath)
main.Flagparse(&argc, (**string)(&argv), usage)
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 (yy) Lex(v *yySymType) int {
var av asm.Yylval
tok := asm.Yylex(&av)
v.sym = av.Sym
v.lval = av.Lval
v.sval = av.Sval
v.dval = av.Dval
return tok
}
func assemble(file string) int {
var ofile string
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
}
}
func (yy) Error(msg string) {
asm.Yyerror("%s", msg)
}
obj.Writeobj(ctxt, &obuf)
obj.Bflush(&obuf)
return 0
func yyparse() {
yyParse(yy{})
}
var itab = []struct {
name string
type_ uint16
value uint16
}{
var lexinit = []asm.Lextab{
{"SP", LSP, x86.D_AUTO},
{"SB", LSB, x86.D_EXTERN},
{"FP", LFP, x86.D_PARAM},
......@@ -1019,31 +915,11 @@ var itab = []struct {
}
func cinit() {
var s *Sym
var i int
nullgen.Type_ = 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 {
case 1,
2,
......@@ -1055,11 +931,6 @@ func checkscale(scale int) {
yyerror("scale must be 1248: %d", scale)
}
func syminit(s *Sym) {
s.type_ = LNAME
s.value = 0
}
func cclean() {
var g2 Addr2
......@@ -1070,24 +941,30 @@ func cclean() {
var lastpc *obj.Prog
type Addr2 struct {
from obj.Addr
to obj.Addr
}
func outcode(a int, g2 *Addr2) {
var p *obj.Prog
var pl *obj.Plist
if pass == 1 {
if asm.Pass == 1 {
goto out
}
p = new(obj.Prog)
*p = obj.Prog{}
p.Ctxt = asm.Ctxt
p.As = int16(a)
p.Lineno = stmtline
p.From = g2.from
p.To = g2.to
p.Pc = int64(pc)
p.Pc = int64(asm.PC)
if lastpc == nil {
pl = obj.Linknewplist(ctxt)
pl = obj.Linknewplist(asm.Ctxt)
pl.Firstpc = p
} else {
......@@ -1097,6 +974,6 @@ func outcode(a int, g2 *Addr2) {
out:
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